/* 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; }
static OpcUa_StatusCode OpcUa_UadpExtendedNetworkMessageHeader_WriteBinary(OpcUa_UadpNetworkMessage* a_pValue, OpcUa_Byte **a_pBuffer, OpcUa_UInt32 *a_pSize) { OpcUa_Int32 ii; OpcUa_InitializeStatus(OpcUa_Module_PubSub, "OpcUa_UadpExtendedNetworkMessageHeader_WriteBinary") if(a_pValue->NetworkMessageHeader.NetworkMessageFlags & OpcUa_UadpNetworkMessageFlags_Timestamp) { /* convert structure to UInt64 */ OpcUa_UInt64 timeValue; timeValue = (OpcUa_UInt32)a_pValue->NetworkMessageHeader.Timestamp.dwHighDateTime; timeValue <<= 32; timeValue += (OpcUa_UInt32)a_pValue->NetworkMessageHeader.Timestamp.dwLowDateTime; OpcUa_UadpEncode_Direct(UInt64, &timeValue); } if(a_pValue->NetworkMessageHeader.NetworkMessageFlags & OpcUa_UadpNetworkMessageFlags_PicoSeconds) { OpcUa_UadpEncode_Direct(UInt16, &a_pValue->NetworkMessageHeader.PicoSeconds); } if(a_pValue->NetworkMessageHeader.NetworkMessageFlags & OpcUa_UadpNetworkMessageFlags_PromotedFields) { OpcUa_Byte *pSizeBuffer; OpcUa_UInt16_Wire totalSize16_Wire; OpcUa_UInt16 totalSize16; if(*a_pSize < sizeof(OpcUa_UInt16_Wire)) { OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError); } pSizeBuffer = *a_pBuffer; *a_pBuffer += sizeof(OpcUa_UInt16_Wire); *a_pSize -= sizeof(OpcUa_UInt16_Wire); for(ii = 0; ii < a_pValue->NetworkMessageHeader.NoOfPromotedFields; ii++) { if(a_pValue->NetworkMessageHeader.PromotedFields[ii] >= a_pValue->Payload[0].KeyOrEventMessage.NoOfDataSetFields) { OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError); } uStatus = OpcUa_UadpDataSetField_WriteBinary(a_pValue->Payload[0].KeyOrEventMessage.DataSetFields[a_pValue->NetworkMessageHeader.PromotedFields[ii]], a_pValue->Payload[0].Header.FieldEncoding, a_pBuffer, a_pSize); OpcUa_GotoErrorIfBad(uStatus); } totalSize16 = (OpcUa_UInt16)(*a_pBuffer - pSizeBuffer) - sizeof(OpcUa_UInt16_Wire); uStatus = OpcUa_UInt16_P_NativeToWire(&totalSize16_Wire, &totalSize16); OpcUa_GotoErrorIfBad(uStatus); memcpy(pSizeBuffer, &totalSize16_Wire, sizeof(OpcUa_UInt16_Wire)); } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; /* nothing to do */ OpcUa_FinishErrorHandling; }
/*============================================================================ * Create a new signal socket *===========================================================================*/ OpcUa_StatusCode OpcUa_P_SocketManager_NewSignalSocket(OpcUa_SocketManager a_pSocketManager) { OpcUa_InternalSocket* pIntSignalSocket = OpcUa_Null; OpcUa_InternalSocketManager* pInternalSocketManager = (OpcUa_InternalSocketManager*)a_pSocketManager; OpcUa_InitializeStatus(OpcUa_Module_Socket, "NewSignalSocket"); OpcUa_GotoErrorIfArgumentNull(a_pSocketManager); pIntSignalSocket = (OpcUa_InternalSocket*)OpcUa_SocketManager_FindFreeSocket(a_pSocketManager, OpcUa_True); if(pIntSignalSocket == OpcUa_Null) { uStatus = OpcUa_BadResourceUnavailable; goto Error; } uStatus = OpcUa_P_RawSocket_CreateSocketPair( &pIntSignalSocket->rawSocket, &pInternalSocketManager->pCookie); OpcUa_GotoErrorIfBad(uStatus); pIntSignalSocket->Flags.EventMask = OPCUA_SOCKET_CLOSE_EVENT | OPCUA_SOCKET_READ_EVENT | OPCUA_SOCKET_EXCEPT_EVENT | OPCUA_SOCKET_TIMEOUT_EVENT; uStatus = OpcUa_P_RawSocket_SetBlockMode (pIntSignalSocket->rawSocket, OpcUa_False); if (OpcUa_IsBad(uStatus)) { OpcUa_P_RawSocket_Close(pIntSignalSocket->rawSocket); OpcUa_P_RawSocket_Close(pInternalSocketManager->pCookie); OpcUa_GotoErrorWithStatus(uStatus); } uStatus = OpcUa_P_RawSocket_SetBlockMode (pInternalSocketManager->pCookie, OpcUa_False); if (OpcUa_IsBad(uStatus)) { OpcUa_P_RawSocket_Close(pIntSignalSocket->rawSocket); OpcUa_P_RawSocket_Close(pInternalSocketManager->pCookie); OpcUa_GotoErrorWithStatus(uStatus); } OPCUA_SOCKET_SETVALID(pIntSignalSocket); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pIntSignalSocket) { pIntSignalSocket->rawSocket = (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID; OPCUA_SOCKET_INVALIDATE(pIntSignalSocket); } OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_X509_AddCustomExtension *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_X509_AddCustomExtension( X509** a_ppCertificate, OpcUa_Crypto_Extension* a_pExtension, X509V3_CTX* a_pX509V3Context) { X509_EXTENSION* pExtension = OpcUa_Null; char* pName = OpcUa_Null; char* pValue = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_AddCustomExtension"); OpcUa_ReturnErrorIfArgumentNull(a_pX509V3Context); OpcUa_ReturnErrorIfArgumentNull(a_pExtension->key); OpcUa_ReturnErrorIfArgumentNull(a_pExtension->value); pName = (char*)a_pExtension->key; pValue = (char*)a_pExtension->value; /* create the extension. */ pExtension = X509V3_EXT_conf( OpcUa_Null, a_pX509V3Context, pName, pValue); if(pExtension == OpcUa_Null) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* add it to the certificate. */ if(!X509_add_ext(*a_ppCertificate, pExtension, -1)) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* free the extension. */ X509_EXTENSION_free(pExtension); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pExtension != OpcUa_Null) { X509_EXTENSION_free(pExtension); } OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_TcpSecureChannel_CheckSequenceNumber *===========================================================================*/ OpcUa_StatusCode OpcUa_TcpSecureChannel_CheckSequenceNumber(OpcUa_SecureChannel* a_pSecureChannel, OpcUa_UInt32 a_uSequenceNumber) { OpcUa_InitializeStatus(OpcUa_Module_SecureChannel, "CheckSequenceNumber"); OpcUa_ReturnErrorIfArgumentNull(a_pSecureChannel); OPCUA_SECURECHANNEL_LOCK(a_pSecureChannel); /* The SequenceNumber shall also monotonically increase for all Messages and shall not wrap around until it is greater than 4 294 966 271 (UInt32.MaxValue - 1 024). The first number after the wrap around shall be less than 1 024. */ if(!((a_uSequenceNumber == a_pSecureChannel->uLastSequenceNumberRcvd + 1) || ((a_uSequenceNumber < 1024) && (a_pSecureChannel->uLastSequenceNumberRcvd > 4294966271u)))) { OpcUa_GotoErrorWithStatus(OpcUa_BadSequenceNumberInvalid); } a_pSecureChannel->uLastSequenceNumberRcvd = a_uSequenceNumber; OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); OpcUa_FinishErrorHandling; }
/*============================================================================ * 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; }
/*============================================================================ * OpcUa_P_OpenSSL_AES_CBC_decrypt *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_AES_CBC_Decrypt( OpcUa_CryptoProvider* a_pProvider, OpcUa_Byte* a_pCipherText, OpcUa_UInt32 a_cipherTextLen, OpcUa_Key* a_key, OpcUa_Byte* a_pInitalVector, OpcUa_Byte* a_pPlainText, OpcUa_UInt32* a_pPlainTextLen) { AES_KEY key; OpcUa_Byte pInitalVector[16]; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "AES_CBC_Decrypt"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pCipherText); OpcUa_ReturnErrorIfArgumentNull(a_key); OpcUa_ReturnErrorIfArgumentNull(a_key->Key.Data); OpcUa_ReturnErrorIfArgumentNull(a_pInitalVector); OpcUa_ReturnErrorIfArgumentNull(a_pPlainTextLen); if(a_cipherTextLen % 16 != 0) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } *a_pPlainTextLen = a_cipherTextLen; /* if just the output length is needed for the caller of this function */ if(a_pPlainText == OpcUa_Null) { OpcUa_ReturnStatusCode; } /* we have to pass the key length in bits instead of bytes */ if(AES_set_decrypt_key(a_key->Key.Data, a_key->Key.Length * 8, &key) < 0) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* copy the IV because the AES_cbc_encrypt function overwrites it. */ OpcUa_P_Memory_MemCpy(pInitalVector, 16, a_pInitalVector, 16); /* decrypt ciphertext */ AES_cbc_encrypt( a_pCipherText, a_pPlainText, a_cipherTextLen, &key, pInitalVector, AES_DECRYPT); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
static OpcUa_StatusCode OpcUa_UadpSecurityHeader_WriteBinary(OpcUa_UadpSecurityHeader* a_pValue, OpcUa_Byte **a_pBuffer, OpcUa_UInt32 *a_pSize) { OpcUa_Byte nonceLength; OpcUa_InitializeStatus(OpcUa_Module_PubSub, "OpcUa_UadpSecurityHeader_WriteBinary"); OpcUa_ReturnErrorIfArgumentNull(a_pValue); OpcUa_ReturnErrorIfArgumentNull(a_pBuffer); OpcUa_ReturnErrorIfArgumentNull(*a_pBuffer); OpcUa_ReturnErrorIfArgumentNull(a_pSize); OpcUa_UadpEncode_Direct(Byte, &a_pValue->SecurityFlags); OpcUa_UadpEncode_Direct(UInt32, &a_pValue->SecurityTokenId); /* The nonce is stored as ByteString, but the length has to be encoded as Byte */ if(a_pValue->MessageNonce.Length < 0 || a_pValue->MessageNonce.Length > 0xFF) { OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError); } nonceLength = (OpcUa_Byte)a_pValue->MessageNonce.Length; OpcUa_UadpEncode_Direct(Byte, &nonceLength); if(*a_pSize < nonceLength) { OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError); } memcpy(*a_pBuffer, a_pValue->MessageNonce.Data, nonceLength); *a_pBuffer += nonceLength; *a_pSize -= nonceLength; if(a_pValue->SecurityFlags & OpcUa_UadpSecurityHeader_SecurityFlags_FooterEnabled) { OpcUa_UadpEncode_Direct(UInt16, &a_pValue->SecurityFooterSize); } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; /* nothing to do */ OpcUa_FinishErrorHandling; }
/*============================================================================ * 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; }
/*============================================================================ * 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; }
/*===========================================================================* 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; }
/* 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_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; }
/*============================================================================ * OpcUa_ProxyStub_UpdateConfigString *===========================================================================*/ static OpcUa_StatusCode OpcUa_ProxyStub_UpdateConfigString() { OpcUa_Int iRes = 0; OpcUa_Int iPos = 0; OpcUa_InitializeStatus(OpcUa_Module_ProxyStub, "UpdateConfigString"); #if OPCUA_USE_SYNCHRONISATION OPCUA_P_MUTEX_LOCK(OpcUa_ProxyStub_g_hGlobalsMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ if(OpcUa_ProxyStub_g_pConfigString == OpcUa_Null) { OpcUa_ProxyStub_g_pConfigString = (OpcUa_StringA) OpcUa_Alloc(OPCUA_CONFIG_STRING_SIZE + 1); OpcUa_GotoErrorIfAllocFailed(OpcUa_ProxyStub_g_pConfigString); OpcUa_MemSet(OpcUa_ProxyStub_g_pConfigString, 0, OPCUA_CONFIG_STRING_SIZE + 1); } #if OPCUA_USE_SAFE_FUNCTIONS iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "TraceEnabled", (OpcUa_ProxyStub_g_Configuration.bProxyStub_Trace_Enabled != 0)?1:0); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadInternalError);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "TraceLevel", OpcUa_ProxyStub_g_Configuration.uProxyStub_Trace_Level); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSerializer_MaxAlloc", OpcUa_ProxyStub_g_Configuration.iSerializer_MaxAlloc); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSerializer_MaxStringLength", OpcUa_ProxyStub_g_Configuration.iSerializer_MaxStringLength); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSerializer_MaxByteStringLength", OpcUa_ProxyStub_g_Configuration.iSerializer_MaxByteStringLength); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSerializer_MaxArrayLength", OpcUa_ProxyStub_g_Configuration.iSerializer_MaxArrayLength); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSerializer_MaxMessageSize", OpcUa_ProxyStub_g_Configuration.iSerializer_MaxMessageSize); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "bSecureListener_ThreadPool_Enabled", (OpcUa_ProxyStub_g_Configuration.bSecureListener_ThreadPool_Enabled != 0)?1:0); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSecureListener_ThreadPool_MinThreads", OpcUa_ProxyStub_g_Configuration.iSecureListener_ThreadPool_MinThreads); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSecureListener_ThreadPool_MaxThreads", OpcUa_ProxyStub_g_Configuration.iSecureListener_ThreadPool_MaxThreads); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSecureListener_ThreadPool_MaxJobs", OpcUa_ProxyStub_g_Configuration.iSecureListener_ThreadPool_MaxJobs); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "bSecureListener_ThreadPool_BlockOnAdd", (OpcUa_ProxyStub_g_Configuration.bSecureListener_ThreadPool_BlockOnAdd != 0)?1:0); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "uSecureListener_ThreadPool_Timeout", OpcUa_ProxyStub_g_Configuration.uSecureListener_ThreadPool_Timeout); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "bTcpListener_ClientThreadsEnabled", (OpcUa_ProxyStub_g_Configuration.bTcpListener_ClientThreadsEnabled != 0)?1:0); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iTcpListener_DefaultChunkSize", OpcUa_ProxyStub_g_Configuration.iTcpListener_DefaultChunkSize); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iTcpConnection_DefaultChunkSize", OpcUa_ProxyStub_g_Configuration.iTcpConnection_DefaultChunkSize); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iTcpTransport_MaxMessageLength", OpcUa_ProxyStub_g_Configuration.iTcpTransport_MaxMessageLength); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iTcpTransport_MaxChunkCount", OpcUa_ProxyStub_g_Configuration.iTcpTransport_MaxChunkCount); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "bTcpStream_ExpectWriteToBlock", (OpcUa_ProxyStub_g_Configuration.bTcpStream_ExpectWriteToBlock != 0)?1:0); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} #else /* OPCUA_USE_SAFE_FUNCTIONS */ iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "TraceEnabled", (OpcUa_ProxyStub_g_Configuration.bProxyStub_Trace_Enabled != 0)?1:0); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadInternalError);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "TraceLevel", OpcUa_ProxyStub_g_Configuration.uProxyStub_Trace_Level); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSerializer_MaxAlloc", OpcUa_ProxyStub_g_Configuration.iSerializer_MaxAlloc); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSerializer_MaxStringLength", OpcUa_ProxyStub_g_Configuration.iSerializer_MaxStringLength); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSerializer_MaxByteStringLength", OpcUa_ProxyStub_g_Configuration.iSerializer_MaxByteStringLength); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSerializer_MaxArrayLength", OpcUa_ProxyStub_g_Configuration.iSerializer_MaxArrayLength); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSerializer_MaxMessageSize", OpcUa_ProxyStub_g_Configuration.iSerializer_MaxMessageSize); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "bSecureListener_ThreadPool_Enabled", (OpcUa_ProxyStub_g_Configuration.bSecureListener_ThreadPool_Enabled != 0)?1:0); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSecureListener_ThreadPool_MinThreads", OpcUa_ProxyStub_g_Configuration.iSecureListener_ThreadPool_MinThreads); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSecureListener_ThreadPool_MaxThreads", OpcUa_ProxyStub_g_Configuration.iSecureListener_ThreadPool_MaxThreads); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iSecureListener_ThreadPool_MaxJobs", OpcUa_ProxyStub_g_Configuration.iSecureListener_ThreadPool_MaxJobs); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "bSecureListener_ThreadPool_BlockOnAdd", (OpcUa_ProxyStub_g_Configuration.bSecureListener_ThreadPool_BlockOnAdd != 0)?1:0); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "uSecureListener_ThreadPool_Timeout", OpcUa_ProxyStub_g_Configuration.uSecureListener_ThreadPool_Timeout); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "bTcpListener_ClientThreadsEnabled", (OpcUa_ProxyStub_g_Configuration.bTcpListener_ClientThreadsEnabled != 0)?1:0); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iTcpListener_DefaultChunkSize", OpcUa_ProxyStub_g_Configuration.iTcpListener_DefaultChunkSize); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iTcpConnection_DefaultChunkSize", OpcUa_ProxyStub_g_Configuration.iTcpConnection_DefaultChunkSize); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iTcpTransport_MaxMessageLength", OpcUa_ProxyStub_g_Configuration.iTcpTransport_MaxMessageLength); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%i\\", "iTcpTransport_MaxChunkCount", OpcUa_ProxyStub_g_Configuration.iTcpTransport_MaxChunkCount); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} iRes = OpcUa_SnPrintfA(&OpcUa_ProxyStub_g_pConfigString[iPos], OPCUA_CONFIG_STRING_SIZE - iPos, "%s:%u\\", "bTcpStream_ExpectWriteToBlock", (OpcUa_ProxyStub_g_Configuration.bTcpStream_ExpectWriteToBlock != 0)?1:0); if(iRes > 0){iPos += iRes;}else{OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);} #endif /* OPCUA_USE_SAFE_FUNCTIONS */ #if OPCUA_USE_SYNCHRONISATION OPCUA_P_MUTEX_UNLOCK(OpcUa_ProxyStub_g_hGlobalsMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_ProxyStub_ReInitialize *===========================================================================*/ OpcUa_StatusCode OPCUA_DLLCALL OpcUa_ProxyStub_ReInitialize(OpcUa_ProxyStubConfiguration* a_pProxyStubConfiguration) { OpcUa_InitializeStatus(OpcUa_Module_ProxyStub, "ReInitialize"); #if OPCUA_USE_SYNCHRONISATION OPCUA_P_MUTEX_LOCK(OpcUa_ProxyStub_g_hGlobalsMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ OpcUa_GotoErrorIfArgumentNull(a_pProxyStubConfiguration); if((OpcUa_ProxyStub_g_uNoOfChannels != 0) || (OpcUa_ProxyStub_g_uNoOfEndpoints != 0)) { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidState); } /* set global configuration object */ OpcUa_ProxyStub_g_Configuration = *a_pProxyStubConfiguration; /* check for negative values and fall back to default values in opcua_config.h */ if(OpcUa_ProxyStub_g_Configuration.iSerializer_MaxAlloc == -1) { OpcUa_ProxyStub_g_Configuration.iSerializer_MaxAlloc = OPCUA_SERIALIZER_MAXALLOC; /* currently unused */ } if(OpcUa_ProxyStub_g_Configuration.iSerializer_MaxStringLength == -1) { OpcUa_ProxyStub_g_Configuration.iSerializer_MaxStringLength = OPCUA_ENCODER_MAXSTRINGLENGTH; } if(OpcUa_ProxyStub_g_Configuration.iSerializer_MaxByteStringLength == -1) { OpcUa_ProxyStub_g_Configuration.iSerializer_MaxByteStringLength = OPCUA_ENCODER_MAXBYTESTRINGLENGTH; } if(OpcUa_ProxyStub_g_Configuration.iSerializer_MaxArrayLength == -1) { OpcUa_ProxyStub_g_Configuration.iSerializer_MaxArrayLength = OPCUA_ENCODER_MAXARRAYLENGTH; } if(OpcUa_ProxyStub_g_Configuration.iSerializer_MaxMessageSize == -1) { OpcUa_ProxyStub_g_Configuration.iSerializer_MaxMessageSize = OPCUA_ENCODER_MAXMESSAGELENGTH; } if(OpcUa_ProxyStub_g_Configuration.iSecureListener_ThreadPool_MinThreads == -1) { OpcUa_ProxyStub_g_Configuration.iSecureListener_ThreadPool_MinThreads = OPCUA_SECURELISTENER_THREADPOOL_MINTHREADS; } if(OpcUa_ProxyStub_g_Configuration.iSecureListener_ThreadPool_MaxThreads == -1) { OpcUa_ProxyStub_g_Configuration.iSecureListener_ThreadPool_MaxThreads = OPCUA_SECURELISTENER_THREADPOOL_MAXTHREADS; } if(OpcUa_ProxyStub_g_Configuration.iSecureListener_ThreadPool_MaxJobs == -1) { OpcUa_ProxyStub_g_Configuration.iSecureListener_ThreadPool_MaxJobs = OPCUA_SECURELISTENER_THREADPOOL_MAXJOBS; } if(OpcUa_ProxyStub_g_Configuration.iTcpListener_DefaultChunkSize == -1) { OpcUa_ProxyStub_g_Configuration.iTcpListener_DefaultChunkSize = OPCUA_TCPLISTENER_DEFAULTCHUNKSIZE; } if(OpcUa_ProxyStub_g_Configuration.iTcpConnection_DefaultChunkSize == -1) { OpcUa_ProxyStub_g_Configuration.iTcpConnection_DefaultChunkSize = OPCUA_TCPCONNECTION_DEFAULTCHUNKSIZE; } if(OpcUa_ProxyStub_g_Configuration.iTcpTransport_MaxChunkCount == -1) { OpcUa_ProxyStub_g_Configuration.iTcpTransport_MaxChunkCount = 0; } if(OpcUa_ProxyStub_g_Configuration.iTcpTransport_MaxMessageLength == -1) { OpcUa_ProxyStub_g_Configuration.iTcpTransport_MaxMessageLength = OPCUA_ENCODER_MAXMESSAGELENGTH; } #if OPCUA_USE_SYNCHRONISATION OPCUA_P_MUTEX_UNLOCK(OpcUa_ProxyStub_g_hGlobalsMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; #if OPCUA_USE_SYNCHRONISATION OPCUA_P_MUTEX_UNLOCK(OpcUa_ProxyStub_g_hGlobalsMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_SecureChannel_Open *===========================================================================*/ OpcUa_StatusCode OpcUa_TcpSecureChannel_Open( OpcUa_SecureChannel* a_pSecureChannel, OpcUa_Handle a_hTransportConnection, OpcUa_ChannelSecurityToken a_channelSecurityToken, OpcUa_MessageSecurityMode a_messageSecurityMode, OpcUa_ByteString* a_pbsClientCertificate, OpcUa_ByteString* a_pbsServerCertificate, OpcUa_SecurityKeyset* a_pReceivingKeyset, OpcUa_SecurityKeyset* a_pSendingKeyset, OpcUa_CryptoProvider* a_pCryptoProvider) { OpcUa_InitializeStatus(OpcUa_Module_SecureChannel, "Open"); OpcUa_ReturnErrorIfArgumentNull(a_pSecureChannel); OpcUa_ReturnErrorIfArgumentNull(a_hTransportConnection); OpcUa_ReturnErrorIfArgumentNull(a_pCryptoProvider); OPCUA_SECURECHANNEL_LOCK(a_pSecureChannel); if(a_pSecureChannel->SecureChannelId != a_channelSecurityToken.ChannelId) { OpcUa_GotoErrorWithStatus(OpcUa_BadSecureChannelIdInvalid); } a_pSecureChannel->bCurrentTokenActive = OpcUa_True; /*** TCP SECURECHANNEL ***/ a_pSecureChannel->CurrentChannelSecurityToken.ChannelId = a_channelSecurityToken.ChannelId; a_pSecureChannel->CurrentChannelSecurityToken.TokenId = a_channelSecurityToken.TokenId; a_pSecureChannel->CurrentChannelSecurityToken.CreatedAt = a_channelSecurityToken.CreatedAt; a_pSecureChannel->CurrentChannelSecurityToken.RevisedLifetime = a_channelSecurityToken.RevisedLifetime; /*** SECURECHANNEL ***/ a_pSecureChannel->State = OpcUa_SecureChannelState_Opened; a_pSecureChannel->TransportConnection = a_hTransportConnection; a_pSecureChannel->MessageSecurityMode = a_messageSecurityMode; a_pSecureChannel->uExpirationCounter = (OpcUa_UInt32)(a_pSecureChannel->CurrentChannelSecurityToken.RevisedLifetime/OPCUA_SECURELISTENER_WATCHDOG_INTERVAL); a_pSecureChannel->uOverlapCounter = (OpcUa_UInt32)((a_pSecureChannel->CurrentChannelSecurityToken.RevisedLifetime>>2)/OPCUA_SECURELISTENER_WATCHDOG_INTERVAL); /* copy client certificate */ if(a_pbsClientCertificate != OpcUa_Null && a_pbsClientCertificate->Length > 0) { a_pSecureChannel->ClientCertificate.Data = (OpcUa_Byte *)OpcUa_Alloc(a_pbsClientCertificate->Length); OpcUa_GotoErrorIfAllocFailed(a_pSecureChannel->ClientCertificate.Data); a_pSecureChannel->ClientCertificate.Length = a_pbsClientCertificate->Length; OpcUa_MemCpy( a_pSecureChannel->ClientCertificate.Data, a_pSecureChannel->ClientCertificate.Length, a_pbsClientCertificate->Data, a_pbsClientCertificate->Length); } else { OpcUa_ByteString_Initialize(&a_pSecureChannel->ClientCertificate); } if(a_pbsServerCertificate != OpcUa_Null && a_pbsServerCertificate->Length > 0) { a_pSecureChannel->ServerCertificate.Data = (OpcUa_Byte*)OpcUa_Alloc(a_pbsServerCertificate->Length); OpcUa_GotoErrorIfAllocFailed(a_pSecureChannel->ServerCertificate.Data); a_pSecureChannel->ServerCertificate.Length = a_pbsServerCertificate->Length; OpcUa_MemCpy( a_pSecureChannel->ServerCertificate.Data, a_pSecureChannel->ServerCertificate.Length, a_pbsServerCertificate->Data, a_pbsServerCertificate->Length); } else { OpcUa_ByteString_Initialize(&a_pSecureChannel->ServerCertificate); } a_pSecureChannel->pCurrentReceivingKeyset = a_pReceivingKeyset; a_pSecureChannel->pCurrentSendingKeyset = a_pSendingKeyset; a_pSecureChannel->pCurrentCryptoProvider = a_pCryptoProvider; OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_SecurityKeyset_Clear(a_pReceivingKeyset); OpcUa_SecurityKeyset_Clear(a_pSendingKeyset); OpcUa_Free(a_pReceivingKeyset); OpcUa_Free(a_pSendingKeyset); OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_CertificateStore_Open *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_OpenCertificateStore( OpcUa_PKIProvider* a_pProvider, OpcUa_Void** a_ppCertificateStore) /* type depends on store implementation */ { OpcUa_P_OpenSSL_CertificateStore_Config* pCertificateStoreCfg; X509_STORE* pStore; X509_LOOKUP* pLookup; char CertFile[MAX_PATH]; struct dirent **dirlist = NULL; int numCertificates = 0, i; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_OpenCertificateStore"); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pProvider->Handle); OpcUa_ReturnErrorIfArgumentNull(a_ppCertificateStore); *a_ppCertificateStore = OpcUa_Null; pCertificateStoreCfg = (OpcUa_P_OpenSSL_CertificateStore_Config*)a_pProvider->Handle; if(!(*a_ppCertificateStore = pStore = X509_STORE_new())) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } X509_STORE_set_verify_cb_func(pStore, OpcUa_P_OpenSSL_CertificateStore_Verify_Callback); if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_USE_DEFAULT_CERT_CRL_LOOKUP_METHOD) { if(X509_STORE_set_default_paths(pStore) != 1) { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_STORE_set_default_paths!\n"); OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } if(!(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_DONT_ADD_TRUST_LIST_TO_ROOT_CERTIFICATES)) { if(pCertificateStoreCfg->CertificateTrustListLocation == OpcUa_Null || pCertificateStoreCfg->CertificateTrustListLocation[0] == '\0') { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* how to search for certificate & CRLs */ if(!(pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file()))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* how to search for certificate & CRLs */ numCertificates = scandir(pCertificateStoreCfg->CertificateTrustListLocation, &dirlist, certificate_filter_der, alphasort); for (i=0; i<numCertificates; i++) { uStatus = OpcUa_P_OpenSSL_BuildFullPath(pCertificateStoreCfg->CertificateTrustListLocation, dirlist[i]->d_name, MAX_PATH, CertFile); OpcUa_GotoErrorIfBad(uStatus); /* add CACertificate lookup */ if(X509_LOOKUP_load_file(pLookup, CertFile, X509_FILETYPE_ASN1) != 1) /*DER encoded*/ { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_LOOKUP_load_file: skipping %s\n", CertFile); } } for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); dirlist = NULL; } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_ADD_UNTRUSTED_LIST_TO_ROOT_CERTIFICATES) { if(pCertificateStoreCfg->CertificateUntrustedListLocation == OpcUa_Null || pCertificateStoreCfg->CertificateUntrustedListLocation[0] == '\0') { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_UNTRUSTED_LIST_IS_INDEX) { /* how to search for certificate */ if(!(pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir()))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* add hash lookup */ if(X509_LOOKUP_add_dir(pLookup, pCertificateStoreCfg->CertificateUntrustedListLocation, X509_FILETYPE_ASN1) != 1) /*DER encoded*/ { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_LOOKUP_add_dir!\n"); OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } else { /* how to search for certificate & CRLs */ if(!(pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file()))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } numCertificates = scandir(pCertificateStoreCfg->CertificateUntrustedListLocation, &dirlist, certificate_filter_der, alphasort); for (i=0; i<numCertificates; i++) { uStatus = OpcUa_P_OpenSSL_BuildFullPath(pCertificateStoreCfg->CertificateUntrustedListLocation, dirlist[i]->d_name, MAX_PATH, CertFile); OpcUa_GotoErrorIfBad(uStatus); /* add CACertificate lookup */ if(X509_LOOKUP_load_file(pLookup, CertFile, X509_FILETYPE_ASN1) != 1) /*DER encoded*/ { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_LOOKUP_load_file: skipping %s\n", CertFile); } } for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); dirlist = NULL; } } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL) { if(pCertificateStoreCfg->CertificateRevocationListLocation == OpcUa_Null || pCertificateStoreCfg->CertificateRevocationListLocation[0] == '\0') { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_REVOCATION_LIST_IS_INDEX) { /* how to search for certificate & CRLs */ if(!(pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir()))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* add CRL lookup */ if(X509_LOOKUP_add_dir(pLookup, pCertificateStoreCfg->CertificateRevocationListLocation, X509_FILETYPE_PEM) != 1) /*PEM encoded*/ { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_LOOKUP_add_dir!\n"); OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } else if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_REVOCATION_LIST_IS_CONCATENATED_PEM_FILE) { /* how to search for certificate & CRLs */ if(!(pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file()))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* add CRL lookup */ if(X509_load_crl_file(pLookup, pCertificateStoreCfg->CertificateRevocationListLocation, X509_FILETYPE_PEM) != 1) /*PEM encoded*/ { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_load_crl_file!\n"); } } else { /* how to search for certificate & CRLs */ if(!(pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file()))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } numCertificates = scandir(pCertificateStoreCfg->CertificateRevocationListLocation, &dirlist, certificate_filter_crl, alphasort); for (i=0; i<numCertificates; i++) { uStatus = OpcUa_P_OpenSSL_BuildFullPath(pCertificateStoreCfg->CertificateRevocationListLocation, dirlist[i]->d_name, MAX_PATH, CertFile); OpcUa_GotoErrorIfBad(uStatus); if(X509_load_crl_file(pLookup, CertFile, X509_FILETYPE_PEM) != 1) /*PEM encoded*/ { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_load_crl_file: skipping %s\n", CertFile); } } for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); dirlist = NULL; } if((pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL) == OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL) { /* set the flags of the store so that CRLs are consulted */ if(X509_STORE_set_flags(pStore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } else if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ONLY_LEAF) { /* set the flags of the store so that CRLs are consulted */ if(X509_STORE_set_flags(pStore, X509_V_FLAG_CRL_CHECK) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_SELF_SIGNED_SIGNATURE) { /* set the flags of the store so that CRLs are consulted */ if(X509_STORE_set_flags(pStore, X509_V_FLAG_CHECK_SS_SIGNATURE) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_ALLOW_PROXY_CERTIFICATES) { /* set the flags of the store so that CRLs are consulted */ if(X509_STORE_set_flags(pStore, X509_V_FLAG_ALLOW_PROXY_CERTS) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(dirlist != NULL) { for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); } if(*a_ppCertificateStore != OpcUa_Null) { X509_STORE_free((X509_STORE*)*a_ppCertificateStore); *a_ppCertificateStore = OpcUa_Null; } OpcUa_FinishErrorHandling; }
static OpcUa_StatusCode OpcUa_UadpNetworkMessageHeader_WriteBinary(OpcUa_UadpNetworkMessageHeader* a_pValue, OpcUa_Byte **a_pBuffer, OpcUa_UInt32 *a_pSize) { OpcUa_Byte uadpVersionFlags; OpcUa_Byte extendedFlags1; OpcUa_Byte extendedFlags2; OpcUa_UadpDeclare_Context; OpcUa_InitializeStatus(OpcUa_Module_PubSub, "OpcUa_UadpNetworkMessageHeader_WriteBinary"); OpcUa_UadpInit_Context; OpcUa_ReturnErrorIfArgumentNull(a_pValue); OpcUa_ReturnErrorIfArgumentNull(a_pBuffer); OpcUa_ReturnErrorIfArgumentNull(*a_pBuffer); OpcUa_ReturnErrorIfArgumentNull(a_pSize); /* assign the configured part of the flag bytes */ uadpVersionFlags = (OpcUa_Byte)a_pValue->NetworkMessageFlags & 0x60; /* Take Byte 0 only */ /* Bit 0-3: UADP Version, Bit 5: GroupHeader enabled, Bit 6: PayloadHeader enabled */ uadpVersionFlags |= OPCUA_UADP_VERSION & 0x0F; extendedFlags1 = (OpcUa_Byte)((a_pValue->NetworkMessageFlags & 0x7800) >> 8); /* Take Byte 1 only */ /* Bit 3: DataSetClassId enabled, Bit 4: Security enabled, Bit 5: Timestamp enabled, Bit 6: PicoSeconds enabled */ extendedFlags2 = (OpcUa_Byte)((a_pValue->NetworkMessageFlags & 0x1F0000) >> 16); /* Take Byte 2 only */ /* Bit 0: Chunk message, Bit 1: PromotedFields enabled */ /* ExtendedFlags2 Bit 2-4 NetworkMessageType: 000: DataSetMessage, 001: Discovery Request, 010: Discovery Response */ /* calculate the remaining bits */ /* ExtendedFlags1 Bit 0-2 PublisherIdType: */ if(a_pValue->PublisherId.ArrayType != OpcUa_VariantArrayType_Scalar) { OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError); } switch(a_pValue->PublisherId.Datatype) { case OpcUaType_Byte: /* 0x0 */ uadpVersionFlags |= 0x10; /* PublisherId enabled */ break; case OpcUaType_UInt16: extendedFlags1 |= 0x1; uadpVersionFlags |= 0x10; /* PublisherId enabled */ break; case OpcUaType_UInt32: extendedFlags1 |= 0x2; uadpVersionFlags |= 0x10; /* PublisherId enabled */ break; case OpcUaType_UInt64: extendedFlags1 |= 0x3; uadpVersionFlags |= 0x10; /* PublisherId enabled */ break; case OpcUaType_String: extendedFlags1 |= 0x4; uadpVersionFlags |= 0x10; /* PublisherId enabled */ break; case OpcUaType_Null: /* keep PublisherId disabled */ break; default: /* unsupported data type */ OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError); break; } /* ExtendedFlags1 Bit 7 ExtendedFlags2 enabled: */ if(extendedFlags2) { extendedFlags1 |= 0x80; } /* UADPFlags Bit 7 ExtendedFlags1 enabled */ if(extendedFlags1) { uadpVersionFlags |= 0x80; } OpcUa_UadpEncode_Direct(Byte, &uadpVersionFlags); if(extendedFlags1) { OpcUa_UadpEncode_Direct(Byte, &extendedFlags1); } if(extendedFlags2) { OpcUa_UadpEncode_Direct(Byte, &extendedFlags2); } /* cast away the const pointer */ switch(a_pValue->PublisherId.Datatype) { case OpcUaType_Byte: OpcUa_UadpEncode_Direct(Byte, &a_pValue->PublisherId.Value.Byte); break; case OpcUaType_UInt16: OpcUa_UadpEncode_Direct(UInt16, &a_pValue->PublisherId.Value.UInt16); break; case OpcUaType_UInt32: OpcUa_UadpEncode_Direct(UInt32, &a_pValue->PublisherId.Value.UInt32); break; case OpcUaType_UInt64: OpcUa_UadpEncode_Direct(UInt64, &a_pValue->PublisherId.Value.UInt64); break; case OpcUaType_String: OpcUa_UadpEncode_Simple(String, &a_pValue->PublisherId.Value.String); break; case OpcUaType_Null: break; } if(a_pValue->NetworkMessageFlags & OpcUa_UadpNetworkMessageFlags_DataSetClassId) { OpcUa_UadpEncode_Simple(Guid, &a_pValue->DataSetClassId); } OpcUa_UadpClear_Context; OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_UadpClear_Context; OpcUa_FinishErrorHandling; }
OpcUa_StatusCode fill_Variant_for_value_attribute(_VariableKnoten_* p_Node, OpcUa_String* p_Index, OpcUa_DataValue* p_Results) { OpcUa_Int i; OpcUa_StatusCode uStatus = OpcUa_Good; extern my_Variant all_ValueAttribute_of_VariableTypeNodes_VariableNodes[]; OpcUa_ReturnErrorIfArgumentNull(p_Node); /*OpcUa_ReturnErrorIfArgumentNull(p_Index);*/ OpcUa_ReturnErrorIfArgumentNull(p_Results); if(p_Node->ValueIndex == (-1)) { OpcUa_GotoErrorWithStatus(OpcUa_BadNotReadable) } if(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].ArrayType==OpcUa_VariantArrayType_Scalar) { switch(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Datatype) { case OpcUaId_Double: { p_Results->Value.Value.Double=all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Double; fill_datatype_arraytype_in_my_Variant(p_Results,OpcUaId_Double, OpcUa_VariantArrayType_Scalar,0); break; } case OpcUaId_DateTime: { p_Results->Value.Value.DateTime=all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.DateTime; fill_datatype_arraytype_in_my_Variant(p_Results,OpcUaId_DateTime, OpcUa_VariantArrayType_Scalar,0); break; } case OpcUaId_String: { uStatus= OpcUa_String_AttachCopy(&(p_Results->Value.Value.String),all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.String); OpcUa_GotoErrorIfBad(uStatus) fill_datatype_arraytype_in_my_Variant(p_Results,OpcUaId_String, OpcUa_VariantArrayType_Scalar,0); break; } case OpcUaId_UInt32: { p_Results->Value.Value.UInt32=all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.UInt32; fill_datatype_arraytype_in_my_Variant(p_Results,OpcUaId_UInt32, OpcUa_VariantArrayType_Scalar,0); break; } case OpcUaId_Boolean: { p_Results->Value.Value.Boolean=all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Boolean; fill_datatype_arraytype_in_my_Variant(p_Results,OpcUaId_Boolean, OpcUa_VariantArrayType_Scalar,0); break; } } } if(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].ArrayType==OpcUa_VariantArrayType_Array) { switch(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Datatype) { case OpcUaId_Double: { p_Results->Value.Value.Array.Value.DoubleArray=OpcUa_Memory_Alloc((all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length)*sizeof(OpcUa_Double)); OpcUa_GotoErrorIfAllocFailed((p_Results->Value.Value.Array.Value.DoubleArray)) OpcUa_MemCpy((p_Results->Value.Value.Array.Value.DoubleArray),(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length)*sizeof(OpcUa_Double),(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Value.DoubleArray),(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length)*sizeof(OpcUa_Double)); fill_datatype_arraytype_in_my_Variant(p_Results,OpcUaId_Double, OpcUa_VariantArrayType_Array,all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length); break; } case OpcUaId_String: { p_Results->Value.Value.Array.Value.StringArray=OpcUa_Memory_Alloc((all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length)*sizeof(OpcUa_String)); OpcUa_GotoErrorIfAllocFailed((p_Results->Value.Value.Array.Value.DoubleArray)) for(i=0;i<(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length);i++) { uStatus= OpcUa_String_AttachCopy((p_Results->Value.Value.Array.Value.StringArray)+i,*(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Value.StringArray+i)); if(OpcUa_IsBad(uStatus)) OpcUa_GotoError } fill_datatype_arraytype_in_my_Variant(p_Results,OpcUaId_String, OpcUa_VariantArrayType_Array,all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length); break; } case OpcUaId_UInt32: { p_Results->Value.Value.Array.Value.UInt32Array=OpcUa_Memory_Alloc((all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length)*sizeof(OpcUa_UInt32)); OpcUa_GotoErrorIfAllocFailed((p_Results->Value.Value.Array.Value.UInt32Array)) OpcUa_MemCpy((p_Results->Value.Value.Array.Value.UInt32Array),(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length)*sizeof(OpcUa_UInt32),(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Value.UInt32Array),(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length)*sizeof(OpcUa_UInt32)); fill_datatype_arraytype_in_my_Variant(p_Results,OpcUaId_UInt32, OpcUa_VariantArrayType_Array,all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length); break; } case OpcUaId_Boolean: { p_Results->Value.Value.Array.Value.BooleanArray=OpcUa_Memory_Alloc((all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length)*sizeof(OpcUa_Boolean)); OpcUa_GotoErrorIfAllocFailed((p_Results->Value.Value.Array.Value.BooleanArray)) OpcUa_MemCpy((p_Results->Value.Value.Array.Value.BooleanArray),(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length)*sizeof(OpcUa_Boolean),(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Value.BooleanArray),(all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length)*sizeof(OpcUa_Boolean)); fill_datatype_arraytype_in_my_Variant(p_Results,OpcUaId_UInt32, OpcUa_VariantArrayType_Array,all_ValueAttribute_of_VariableTypeNodes_VariableNodes[p_Node->ValueIndex].Value.Array.Length); break; } } } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; p_Results->StatusCode=uStatus; OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_X509_GetPublicKey *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_X509_GetPublicKey( OpcUa_CryptoProvider* a_pProvider, OpcUa_ByteString* a_pCertificate, OpcUa_StringA a_password, /* this could be optional */ OpcUa_Key* a_pPublicKey) { EVP_PKEY* pPublicKey = OpcUa_Null; RSA* pRsaPublicKey = OpcUa_Null; X509* pCertificate = OpcUa_Null; OpcUa_Byte* pBuffer = OpcUa_Null; BIO* bi; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_GetPublicKey"); OpcUa_ReferenceParameter(a_password); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate->Data); OpcUa_ReturnErrorIfArgumentNull(a_pPublicKey); bi = BIO_new(BIO_s_mem()); BIO_write(bi, a_pCertificate->Data, a_pCertificate->Length); pCertificate = d2i_X509_bio(bi, NULL); BIO_free(bi); if(pCertificate == OpcUa_Null) { return OpcUa_BadCertificateInvalid; } /* get EVP_PKEY from X509 certificate */ pPublicKey = X509_get_pubkey(pCertificate); if(pPublicKey == OpcUa_Null) { X509_free(pCertificate); return OpcUa_BadCertificateInvalid; } /* free X509 certificate, since not needed anymore */ X509_free(pCertificate); switch(EVP_PKEY_type(pPublicKey->type)) { case EVP_PKEY_RSA: /* allocate memory for RSA key */ /* get RSA public key from EVP_PKEY */ pRsaPublicKey = EVP_PKEY_get1_RSA(pPublicKey); /* allocate memory for DER encoded bytestring */ a_pPublicKey->Key.Length = i2d_RSAPublicKey(pRsaPublicKey, OpcUa_Null); if(a_pPublicKey->Key.Data == OpcUa_Null) { RSA_free(pRsaPublicKey); pRsaPublicKey = OpcUa_Null; EVP_PKEY_free(pPublicKey); pPublicKey = OpcUa_Null; OpcUa_ReturnStatusCode; } /* convert RSA key to DER encoded bytestring */ pBuffer = a_pPublicKey->Key.Data; a_pPublicKey->Key.Length = i2d_RSAPublicKey(pRsaPublicKey, &pBuffer); a_pPublicKey->Type = OpcUa_Crypto_KeyType_Rsa_Public; /* free memory for RSA key */ RSA_free(pRsaPublicKey); pRsaPublicKey = OpcUa_Null; break; case EVP_PKEY_EC: case EVP_PKEY_DSA: case EVP_PKEY_DH: default: OpcUa_GotoErrorWithStatus(OpcUa_BadNotSupported); } /*** clean up ***/ EVP_PKEY_free(pPublicKey); pPublicKey = OpcUa_Null; OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; EVP_PKEY_free(pPublicKey); pPublicKey = OpcUa_Null; OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_SecureChannel_Renew *===========================================================================*/ OpcUa_StatusCode OpcUa_TcpSecureChannel_Renew( OpcUa_SecureChannel* a_pSecureChannel, OpcUa_Handle a_hTransportConnection, OpcUa_ChannelSecurityToken a_ChannelSecurityToken, OpcUa_MessageSecurityMode a_eMessageSecurityMode, OpcUa_ByteString* a_pbsClientCertificate, OpcUa_ByteString* a_pbsServerCertificate, OpcUa_SecurityKeyset* a_pNewReceivingKeyset, OpcUa_SecurityKeyset* a_pNewSendingKeyset, OpcUa_CryptoProvider* a_pNewCryptoProvider) { OpcUa_InitializeStatus(OpcUa_Module_SecureChannel, "Renew"); OpcUa_ReturnErrorIfArgumentNull(a_pSecureChannel); OpcUa_ReturnErrorIfArgumentNull(a_hTransportConnection); OpcUa_ReturnErrorIfArgumentNull(a_pNewCryptoProvider); OPCUA_SECURECHANNEL_LOCK(a_pSecureChannel); OpcUa_Trace(OPCUA_TRACE_LEVEL_INFO, "OpcUa_TcpSecureChannel_Renew: New token id for channel %u is %u\n", a_pSecureChannel->SecureChannelId, a_ChannelSecurityToken.TokenId); if(a_pSecureChannel->TransportConnection != a_hTransportConnection) { OpcUa_GotoErrorWithStatus(OpcUa_BadSecureChannelIdInvalid); } if(a_pSecureChannel->SecureChannelId != a_ChannelSecurityToken.ChannelId) { OpcUa_GotoErrorWithStatus(OpcUa_BadSecureChannelIdInvalid); } /*** TCP SECURECHANNEL ***/ /* Previous objects will be overwritten by current objects */ a_pSecureChannel->bCurrentTokenActive = OpcUa_False; /* set channelSecurityToken members */ a_pSecureChannel->PreviousChannelSecurityToken.ChannelId = a_pSecureChannel->CurrentChannelSecurityToken.ChannelId; a_pSecureChannel->PreviousChannelSecurityToken.TokenId = a_pSecureChannel->CurrentChannelSecurityToken.TokenId; a_pSecureChannel->PreviousChannelSecurityToken.CreatedAt = a_pSecureChannel->CurrentChannelSecurityToken.CreatedAt; a_pSecureChannel->PreviousChannelSecurityToken.RevisedLifetime = a_pSecureChannel->CurrentChannelSecurityToken.RevisedLifetime; /* set current channelSecurityToken */ a_pSecureChannel->CurrentChannelSecurityToken.ChannelId = a_ChannelSecurityToken.ChannelId; a_pSecureChannel->CurrentChannelSecurityToken.TokenId = a_ChannelSecurityToken.TokenId; a_pSecureChannel->CurrentChannelSecurityToken.CreatedAt = a_ChannelSecurityToken.CreatedAt; a_pSecureChannel->CurrentChannelSecurityToken.RevisedLifetime = a_ChannelSecurityToken.RevisedLifetime; /*** SECURECHANNEL ***/ a_pSecureChannel->State = OpcUa_SecureChannelState_Opened; a_pSecureChannel->MessageSecurityMode = a_eMessageSecurityMode; a_pSecureChannel->uExpirationCounter = (OpcUa_UInt32)(a_pSecureChannel->CurrentChannelSecurityToken.RevisedLifetime/OPCUA_SECURELISTENER_WATCHDOG_INTERVAL); a_pSecureChannel->uOverlapCounter = (OpcUa_UInt32)((a_pSecureChannel->CurrentChannelSecurityToken.RevisedLifetime>>2)/OPCUA_SECURELISTENER_WATCHDOG_INTERVAL); /* free old certificate and add new one */ OpcUa_ByteString_Clear(&a_pSecureChannel->ClientCertificate); /* copy client certificate!!! */ if(a_pbsClientCertificate != OpcUa_Null && a_pbsClientCertificate->Length > 0) { a_pSecureChannel->ClientCertificate.Data = (OpcUa_Byte*)OpcUa_Alloc(a_pbsClientCertificate->Length); OpcUa_GotoErrorIfAllocFailed(a_pSecureChannel->ClientCertificate.Data); a_pSecureChannel->ClientCertificate.Length = a_pbsClientCertificate->Length; OpcUa_MemCpy( a_pSecureChannel->ClientCertificate.Data, a_pSecureChannel->ClientCertificate.Length, a_pbsClientCertificate->Data, a_pbsClientCertificate->Length); } /* free old certificate and add new one */ OpcUa_ByteString_Clear(&a_pSecureChannel->ServerCertificate); if(a_pbsServerCertificate != OpcUa_Null && a_pbsServerCertificate->Length > 0) { a_pSecureChannel->ServerCertificate.Data = (OpcUa_Byte*)OpcUa_Alloc(a_pbsServerCertificate->Length); OpcUa_GotoErrorIfAllocFailed(a_pSecureChannel->ServerCertificate.Data); a_pSecureChannel->ServerCertificate.Length = a_pbsServerCertificate->Length; OpcUa_MemCpy( a_pSecureChannel->ServerCertificate.Data, a_pSecureChannel->ServerCertificate.Length, a_pbsServerCertificate->Data, a_pbsServerCertificate->Length); } /* delete previous keysets */ OpcUa_SecurityKeyset_Clear(a_pSecureChannel->pPreviousReceivingKeyset); OpcUa_SecurityKeyset_Clear(a_pSecureChannel->pPreviousSendingKeyset); OpcUa_Free(a_pSecureChannel->pPreviousReceivingKeyset); OpcUa_Free(a_pSecureChannel->pPreviousSendingKeyset); a_pSecureChannel->pPreviousReceivingKeyset = OpcUa_Null; a_pSecureChannel->pPreviousSendingKeyset = OpcUa_Null; /* assign current to previous */ a_pSecureChannel->pPreviousReceivingKeyset = a_pSecureChannel->pCurrentReceivingKeyset; a_pSecureChannel->pPreviousSendingKeyset = a_pSecureChannel->pCurrentSendingKeyset; /* delete previous cryptoprovider */ if( a_pSecureChannel->pPreviousCryptoProvider != OpcUa_Null && a_pSecureChannel->pPreviousCryptoProvider != a_pSecureChannel->pCurrentCryptoProvider) { OPCUA_P_CRYPTOFACTORY_DELETECRYPTOPROVIDER(a_pSecureChannel->pPreviousCryptoProvider); OpcUa_Free(a_pSecureChannel->pPreviousCryptoProvider); a_pSecureChannel->pPreviousCryptoProvider = OpcUa_Null; } else { a_pSecureChannel->pPreviousCryptoProvider = OpcUa_Null; } /* make current cryptoprovider previous */ a_pSecureChannel->pPreviousCryptoProvider = a_pSecureChannel->pCurrentCryptoProvider; a_pSecureChannel->pCurrentCryptoProvider = a_pNewCryptoProvider; a_pSecureChannel->pCurrentReceivingKeyset = a_pNewReceivingKeyset; a_pSecureChannel->pCurrentSendingKeyset = a_pNewSendingKeyset; OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_SecurityKeyset_Clear(a_pNewReceivingKeyset); OpcUa_SecurityKeyset_Clear(a_pNewSendingKeyset); OpcUa_Free(a_pNewReceivingKeyset); OpcUa_Free(a_pNewSendingKeyset); OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); 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_PKI_ValidateCertificate *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_ValidateCertificate( OpcUa_PKIProvider* a_pProvider, OpcUa_ByteString* a_pCertificate, OpcUa_Void* a_pCertificateStore, OpcUa_Int* a_pValidationCode /* Validation return codes from OpenSSL */ ) { OpcUa_P_OpenSSL_CertificateStore_Config* pCertificateStoreCfg; const unsigned char* p; X509* pX509Certificate = OpcUa_Null; STACK_OF(X509)* pX509Chain = OpcUa_Null; X509_STORE_CTX* verify_ctx = OpcUa_Null; /* holds data used during verification process */ char CertFile[MAX_PATH]; struct dirent **dirlist = NULL; int numCertificates = 0, i; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_ValidateCertificate"); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pProvider->Handle); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); OpcUa_ReturnErrorIfArgumentNull(a_pCertificateStore); OpcUa_ReturnErrorIfArgumentNull(a_pValidationCode); pCertificateStoreCfg = (OpcUa_P_OpenSSL_CertificateStore_Config*)a_pProvider->Handle; /* convert DER encoded bytestring certificate to openssl X509 certificate */ p = a_pCertificate->Data; if(!(pX509Certificate = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Length))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } while(p < a_pCertificate->Data + a_pCertificate->Length) { X509* pX509AddCertificate; if(!(pX509AddCertificate = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Data + a_pCertificate->Length - p))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } if(pX509Chain == NULL) { pX509Chain = sk_X509_new_null(); OpcUa_GotoErrorIfAllocFailed(pX509Chain); } if(!sk_X509_push(pX509Chain, pX509AddCertificate)) { X509_free(pX509AddCertificate); OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } /* create verification context and initialize it */ if(!(verify_ctx = X509_STORE_CTX_new())) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } #if (OPENSSL_VERSION_NUMBER > 0x00907000L) if(X509_STORE_CTX_init(verify_ctx, (X509_STORE*)a_pCertificateStore, pX509Certificate, pX509Chain) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } #else X509_STORE_CTX_init(verify_ctx, (X509_STORE*)a_pCertificateStore, pX509Certificate, pX509Chain); #endif if(X509_STORE_CTX_set_app_data(verify_ctx, pCertificateStoreCfg) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } if((pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL) == OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL_EXCEPT_SELF_SIGNED && !verify_ctx->check_issued(verify_ctx, pX509Certificate, pX509Certificate)) { /* set the flags of the store so that CRLs are consulted */ X509_STORE_CTX_set_flags(verify_ctx, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } /* verify the certificate */ *a_pValidationCode = X509_V_OK; if(X509_verify_cert(verify_ctx) <= 0) { *a_pValidationCode = verify_ctx->error; switch(verify_ctx->error) { case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CRL_NOT_YET_VALID: case X509_V_ERR_CRL_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: { uStatus = OpcUa_BadCertificateTimeInvalid; break; } case X509_V_ERR_CERT_REVOKED: { uStatus = OpcUa_BadCertificateRevoked; break; } case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: { uStatus = OpcUa_BadCertificateUntrusted; break; } case X509_V_ERR_CERT_SIGNATURE_FAILURE: { uStatus = OpcUa_BadSecurityChecksFailed; break; } default: { uStatus = OpcUa_BadCertificateInvalid; } } OpcUa_GotoErrorIfBad(uStatus); } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_REQUIRE_CHAIN_CERTIFICATE_IN_TRUST_LIST) { FILE* pCertificateFile; X509* pTrustCert; STACK_OF(X509)* chain; int trusted, n; chain = X509_STORE_CTX_get_chain(verify_ctx); trusted = 0; if(pCertificateStoreCfg->CertificateTrustListLocation == NULL || pCertificateStoreCfg->CertificateTrustListLocation[0] == '\0') { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } numCertificates = scandir(pCertificateStoreCfg->CertificateTrustListLocation, &dirlist, certificate_filter_der, alphasort); for (i=0; i<numCertificates; i++) { uStatus = OpcUa_P_OpenSSL_BuildFullPath(pCertificateStoreCfg->CertificateTrustListLocation, dirlist[i]->d_name, MAX_PATH, CertFile); OpcUa_GotoErrorIfBad(uStatus); /* read DER certificates */ pCertificateFile = fopen(CertFile, "r"); if(pCertificateFile == OpcUa_Null) { continue; /* ignore access errors */ } pTrustCert = d2i_X509_fp(pCertificateFile, (X509**)OpcUa_Null); fclose(pCertificateFile); if(pTrustCert == OpcUa_Null) { continue; /* ignore parse errors */ } for(n = 0; n < sk_X509_num(chain); n++) { if (X509_cmp(sk_X509_value(chain, n), pTrustCert) == 0) break; } X509_free(pTrustCert); if(n < sk_X509_num(chain)) { trusted = 1; break; } } for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); dirlist = NULL; if(!trusted) { uStatus = OpcUa_BadCertificateUntrusted; OpcUa_GotoErrorIfBad(uStatus); } } X509_STORE_CTX_free(verify_ctx); X509_free(pX509Certificate); if(pX509Chain != OpcUa_Null) { sk_X509_pop_free(pX509Chain, X509_free); } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(dirlist != NULL) { for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); } if(verify_ctx != OpcUa_Null) { X509_STORE_CTX_free(verify_ctx); } if(pX509Certificate != OpcUa_Null) { X509_free(pX509Certificate); } if(pX509Chain != OpcUa_Null) { sk_X509_pop_free(pX509Chain, X509_free); } OpcUa_FinishErrorHandling; }
/*============================================================================ * 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; }