/*============================================================================ * OpcUa_MemoryStream_Read *===========================================================================*/ OpcUa_StatusCode OpcUa_MemoryStream_Read( struct _OpcUa_InputStream* istrm, OpcUa_Byte* buffer, OpcUa_UInt32* count, OpcUa_Stream_PfnOnReadyToRead* callback, OpcUa_Void* callbackData) { OpcUa_MemoryStream* handle = OpcUa_Null; OpcUa_DeclareErrorTraceModule(OpcUa_Module_MemoryStream); OpcUa_ReturnErrorIfArgumentNull(istrm); OpcUa_ReturnErrorIfArgumentNull(buffer); OpcUa_ReturnErrorIfArgumentNull(count); OpcUa_ReturnErrorIfInvalidStream(istrm, Read); OpcUa_ReferenceParameter(callback); OpcUa_ReferenceParameter(callbackData); handle = (OpcUa_MemoryStream*)istrm->Handle; if (handle->Closed) { return OpcUa_BadInvalidState; } return OpcUa_Buffer_Read(handle->pBuffer, buffer, count); }
OpcUa_Void OPCUA_DLLCALL OpcUa_P_Trace( #if OPCUA_TRACE_FILE_LINE_INFO OpcUa_UInt32 level, OpcUa_CharA* sFile, OpcUa_UInt32 line, #endif OpcUa_CharA* a_sMessage) { #if OPCUA_TRACE_FILE_LINE_INFO OpcUa_ReferenceParameter(level); OpcUa_ReferenceParameter(sFile); OpcUa_ReferenceParameter(line); #endif /* send to tracehook if registered */ if(g_OpcUa_P_TraceHook != OpcUa_Null) { g_OpcUa_P_TraceHook(a_sMessage); } else /* send to console */ { char dtbuffer[25]; OpcUa_DateTime timestamp; timestamp = OpcUa_P_DateTime_UtcNow(); OpcUa_P_DateTime_GetStringFromDateTime(timestamp, dtbuffer, 25); printf("|%ld| %s %s", OpcUa_P_Thread_GetCurrentThreadId(), &dtbuffer[11], a_sMessage); } }
/* * ToDo: problems with RSA_PKCS1_OAEP_PADDING -> RSA_PKCS1_PSS_PADDING is * needed (Version 0.9.9); RSA_PKCS1_OAEP_PADDING is just for encryption */ OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Private_Sign( OpcUa_CryptoProvider* a_pProvider, OpcUa_ByteString a_data, OpcUa_Key* a_privateKey, OpcUa_Int16 a_padding, /* e.g. RSA_PKCS1_PADDING */ OpcUa_ByteString* a_pSignature) /* output length >= key length */ { EVP_PKEY* pSSLPrivateKey = OpcUa_Null; const unsigned char* pData = OpcUa_Null; int iErr = 0; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Private_Sign"); /* unused parameters */ OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReferenceParameter(a_padding); /* check parameters */ OpcUa_ReturnErrorIfArgumentNull(a_privateKey); OpcUa_ReturnErrorIfArgumentNull(a_pSignature); pData = a_privateKey->Key.Data; OpcUa_ReturnErrorIfArgumentNull(pData); OpcUa_ReturnErrorIfTrue((a_privateKey->Type != OpcUa_Crypto_KeyType_Rsa_Private), OpcUa_BadInvalidArgument); /* convert private key and check key length against buffer length */ pSSLPrivateKey = d2i_PrivateKey(EVP_PKEY_RSA, OpcUa_Null, &pData, a_privateKey->Key.Length); OpcUa_GotoErrorIfTrue((pSSLPrivateKey == OpcUa_Null), OpcUa_BadUnexpectedError); OpcUa_GotoErrorIfTrue((a_pSignature->Length < RSA_size(pSSLPrivateKey->pkey.rsa)), OpcUa_BadInvalidArgument); /* sign data */ iErr = RSA_sign(NID_sha1, a_data.Data, a_data.Length, a_pSignature->Data, (unsigned int*)&a_pSignature->Length, pSSLPrivateKey->pkey.rsa); OpcUa_GotoErrorIfTrue((iErr != 1), OpcUa_BadUnexpectedError); /* free internal key representation */ EVP_PKEY_free(pSSLPrivateKey); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(OpcUa_IsEqual(OpcUa_BadUnexpectedError)) { long lErr = ERR_get_error(); char* szErr = ERR_error_string(lErr, 0); if(szErr != OpcUa_Null) { OpcUa_P_Trace("*** RSA_Private_Sign: "); OpcUa_P_Trace(szErr); OpcUa_P_Trace(" ***\n"); } } if(pSSLPrivateKey != OpcUa_Null) { EVP_PKEY_free(pSSLPrivateKey); } OpcUa_FinishErrorHandling; }
/* ToDo: problems with RSA_PKCS1_OAEP_PADDING -> find solution */ OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Public_Verify( OpcUa_CryptoProvider* a_pProvider, OpcUa_ByteString a_data, OpcUa_Key* a_publicKey, OpcUa_Int16 a_padding, OpcUa_ByteString* a_pSignature) { EVP_PKEY* pPublicKey = OpcUa_Null; OpcUa_Int32 keySize = 0; const unsigned char *pData; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Public_Verify"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReferenceParameter(a_padding); OpcUa_ReturnErrorIfArgumentNull(a_data.Data); OpcUa_ReturnErrorIfArgumentNull(a_publicKey); OpcUa_ReturnErrorIfArgumentNull(a_publicKey->Key.Data); OpcUa_ReturnErrorIfArgumentNull(a_pSignature); if(a_publicKey->Type != OpcUa_Crypto_KeyType_Rsa_Public) { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument); } pData = a_publicKey->Key.Data; pPublicKey = d2i_PublicKey(EVP_PKEY_RSA,OpcUa_Null, &pData, a_publicKey->Key.Length); if(pPublicKey == OpcUa_Null) { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument); } keySize = RSA_size(pPublicKey->pkey.rsa); if((a_pSignature->Length%keySize) != 0) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } if (RSA_verify(NID_sha1, a_data.Data, a_data.Length, a_pSignature->Data, a_pSignature->Length, pPublicKey->pkey.rsa) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } EVP_PKEY_free(pPublicKey); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if (pPublicKey != OpcUa_Null) { EVP_PKEY_free(pPublicKey); } OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_PKI_NoSecurity_CloseCertificateStore *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_NoSecurity_CloseCertificateStore( OpcUa_PKIProvider* a_pProvider, OpcUa_Void** a_ppCertificateStore) { OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReferenceParameter(a_ppCertificateStore); return OpcUa_BadNotSupported; }
/*============================================================================ * OpcUa_P_OpenSSL_PKI_NoSecurity_LoadCertificate *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_NoSecurity_LoadPrivateKeyFromFile( OpcUa_StringA a_privateKeyFile, OpcUa_P_FileFormat a_fileFormat, OpcUa_StringA a_password, OpcUa_ByteString* a_pPrivateKey) { OpcUa_ReferenceParameter(a_privateKeyFile); OpcUa_ReferenceParameter(a_fileFormat); OpcUa_ReferenceParameter(a_password); OpcUa_ReferenceParameter(a_pPrivateKey); return OpcUa_BadNotSupported; }
/*============================================================================ * OpcUa_P_OpenSSL_PKI_ValidateCertificate *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_NoSecurity_ValidateCertificate( OpcUa_PKIProvider* a_pProvider, OpcUa_ByteString* a_pCertificate, OpcUa_Void* a_pCertificateStore, OpcUa_Int* a_pValidationCode) { OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReferenceParameter(a_pCertificateStore); OpcUa_ReferenceParameter(a_pCertificate); OpcUa_ReferenceParameter(a_pValidationCode); return OpcUa_BadNotSupported; }
/*============================================================================ * OpcUa_P_OpenSSL_PKI_NoSecurity_LoadCertificate *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_NoSecurity_LoadCertificate( OpcUa_PKIProvider* a_pProvider, OpcUa_Void* a_pLoadHandle, OpcUa_Void* a_pCertificateStore, OpcUa_ByteString* a_pCertificate) { OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReferenceParameter(a_pCertificateStore); OpcUa_ReferenceParameter(a_pCertificate); OpcUa_ReferenceParameter(a_pLoadHandle); return OpcUa_BadNotSupported; }
/*============================================================================ * OpcUa_P_OpenSSL_AES_CBC_Encrypt *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_AES_CBC_Encrypt( OpcUa_CryptoProvider* a_pProvider, OpcUa_Byte* a_pPlainText, OpcUa_UInt32 a_plainTextLen, OpcUa_Key* a_key, OpcUa_Byte* a_pInitalVector, OpcUa_Byte* a_pCipherText, OpcUa_UInt32* a_pCipherTextLen) { AES_KEY key; OpcUa_Byte pInitalVector[16]; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "AES_CBC_Encrypt"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pPlainText); OpcUa_ReturnErrorIfArgumentNull(a_key); OpcUa_ReturnErrorIfArgumentNull(a_key->Key.Data); OpcUa_ReturnErrorIfArgumentNull(a_pInitalVector); OpcUa_ReturnErrorIfArgumentNull(a_pCipherTextLen); if(a_plainTextLen % 16 != 0) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } *a_pCipherTextLen = a_plainTextLen; /* if just the output length is needed for the caller of this function */ if(a_pCipherText == OpcUa_Null) { OpcUa_ReturnStatusCode; } /* we have to pass the key length in bits instead of bytes */ if(AES_set_encrypt_key(a_key->Key.Data, a_key->Key.Length * 8, &key) < 0) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* copy the IV because the AES_cbc_encrypt function overwrites it. */ OpcUa_P_Memory_MemCpy(pInitalVector, 16, a_pInitalVector, 16); /* encrypt data */ AES_cbc_encrypt( a_pPlainText, a_pCipherText, a_plainTextLen, &key, pInitalVector, AES_ENCRYPT); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
OpcUa_Boolean OPCUA_DLLCALL OpcUa_Trace_Nop(OpcUa_UInt32 a_uTraceLevel, #if OPCUA_TRACE_FILE_LINE_INFO OpcUa_CharA* a_sFile, OpcUa_UInt32 a_sLine, #endif /* OPCUA_TRACE_FILE_LINE_INFO */ OpcUa_CharA* a_sFormat, ...) { OpcUa_ReferenceParameter(a_uTraceLevel); OpcUa_ReferenceParameter(a_sFormat); #if OPCUA_TRACE_FILE_LINE_INFO OpcUa_ReferenceParameter(a_sFile); OpcUa_ReferenceParameter(a_sLine); #endif /* OPCUA_TRACE_FILE_LINE_INFO */ return OpcUa_False; }
/*============================================================================ * OpcUa_P_OpenSSL_RSA_GenerateKeys *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_GenerateKeys( OpcUa_CryptoProvider* a_pProvider, OpcUa_UInt32 a_bits, OpcUa_Key* a_pPublicKey, OpcUa_Key* a_pPrivateKey) { RSA* pRsa; unsigned char* pData; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_GenerateKeys"); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pPublicKey); OpcUa_ReturnErrorIfArgumentNull(a_pPrivateKey); OpcUa_ReferenceParameter(a_pProvider); /* Just 1024 or 2048 bits should be allowed for compatibility reasons */ if ((a_bits != 1024) && (a_bits != 2048) && (a_bits != 3072) && (a_bits != 4096)) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } if(a_pPublicKey->Key.Data == OpcUa_Null) { a_pPublicKey->Key.Length = a_bits; OpcUa_ReturnStatusCode; } if(a_pPrivateKey->Key.Data == OpcUa_Null) { a_pPrivateKey->Key.Length = a_bits; OpcUa_ReturnStatusCode; } pRsa = RSA_generate_key(a_bits, RSA_F4, NULL, OpcUa_Null); pData = a_pPublicKey->Key.Data; a_pPublicKey->Key.Length = i2d_RSAPublicKey(pRsa, &pData); pData = a_pPrivateKey->Key.Data; a_pPrivateKey->Key.Length = i2d_RSAPrivateKey(pRsa, &pData); /* clean up */ if(pRsa != OpcUa_Null) { RSA_free(pRsa); } a_pPublicKey->Type = OpcUa_Crypto_Rsa_Alg_Id; a_pPrivateKey->Type = OpcUa_Crypto_Rsa_Alg_Id; OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_X509_GetSignature *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_X509_GetSignature( OpcUa_CryptoProvider* a_pProvider, OpcUa_ByteString* a_pCertificate, OpcUa_Signature* a_pSignature) { X509* pX509Certificate = OpcUa_Null; const unsigned char* pTemp = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_GetSignature"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); OpcUa_ReturnErrorIfArgumentNull(a_pSignature); /* d2i_X509 modifies the given pointer -> use local replacement */ pTemp = a_pCertificate->Data; d2i_X509(&pX509Certificate, &pTemp, a_pCertificate->Length); if(pX509Certificate == OpcUa_Null) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } a_pSignature->Signature.Length = pX509Certificate->signature->length; a_pSignature->Algorithm = OBJ_obj2nid(pX509Certificate->sig_alg->algorithm); if(a_pSignature->Algorithm == NID_undef) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(a_pSignature->Signature.Data != OpcUa_Null) { uStatus = OpcUa_P_Memory_MemCpy(a_pSignature->Signature.Data, a_pSignature->Signature.Length, pX509Certificate->signature->data, pX509Certificate->signature->length); } X509_free(pX509Certificate); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pX509Certificate != OpcUa_Null) { X509_free(pX509Certificate); } OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_Random_Key_Generate *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_Random_Key_Generate( OpcUa_CryptoProvider* a_pProvider, OpcUa_Int32 a_keyLen, OpcUa_Key* a_pKey) { OpcUa_CryptoProviderConfig* pConfig = OpcUa_Null; OpcUa_Int32 keyLen = 0; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "Random_Key_Generate"); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pKey); OpcUa_ReferenceParameter(a_pProvider); keyLen = a_keyLen; if(keyLen < 0) { if(a_pProvider->Handle != OpcUa_Null) { /* get default configuration */ pConfig = (OpcUa_CryptoProviderConfig*)a_pProvider->Handle; keyLen = pConfig->SymmetricKeyLength; } else { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } } else if(keyLen > MAX_GENERATED_OUTPUT_LEN) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } a_pKey->Key.Length = keyLen; a_pKey->Type = OpcUa_Crypto_KeyType_Random; if(a_pKey->Key.Data == OpcUa_Null) { OpcUa_ReturnStatusCode; } if(RAND_bytes(a_pKey->Key.Data, a_pKey->Key.Length) == 0) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * Get last socket error. *===========================================================================*/ OpcUa_Int32 OpcUa_P_RawSocket_GetLastError( OpcUa_RawSocket a_RawSocket) { int lastError = 0; OpcUa_ReferenceParameter(a_RawSocket); /* Not needed in this implementation. */ lastError = WSAGetLastError(); return (OpcUa_Int32)lastError; }
/*============================================================================ * Quick Sort *===========================================================================*/ OpcUa_Void OPCUA_DLLCALL OpcUa_P_QSort( OpcUa_Void* pElements, OpcUa_UInt32 nElementCount, OpcUa_UInt32 nElementSize, OpcUa_PfnCompare* pfnCompare, OpcUa_Void* pContext) { /*qsort_s(pElements, nElementCount, nElementSize, pfnCompare, pContext);*/ OpcUa_ReferenceParameter(pContext); qsort(pElements, nElementCount, nElementSize, pfnCompare); }
/** @brief Unlocks the internal mutex and allows other threads to enter the list. Takes no action if a_pList is null Takes no action if the mutex is null @param a_pList [in] Location of the list to leave */ OpcUa_Void OpcUa_List_Leave(OpcUa_List* a_pList) { #if OPCUA_USE_SYNCHRONISATION if(a_pList != OpcUa_Null && a_pList->pMutex != OpcUa_Null) { OPCUA_P_MUTEX_UNLOCK(a_pList->pMutex); } #else /* OPCUA_USE_SYNCHRONISATION */ OpcUa_ReferenceParameter(a_pList); #endif /* OPCUA_USE_SYNCHRONISATION */ }
/*============================================================================ * Binary Search on sorted array *===========================================================================*/ OpcUa_Void* OPCUA_DLLCALL OpcUa_P_BSearch( OpcUa_Void* pKey, OpcUa_Void* pElements, OpcUa_UInt32 nElementCount, OpcUa_UInt32 nElementSize, OpcUa_PfnCompare* pfnCompare, OpcUa_Void* pContext) { /*return bsearch_s(pKey, pElements, nElementCount, nElementSize, pfnCompare, pContext);*/ OpcUa_ReferenceParameter(pContext); return bsearch(pKey, pElements, nElementCount, nElementSize, pfnCompare); }
/*============================================================================ * Set socket user data *===========================================================================*/ static OpcUa_StatusCode OpcUa_P_SocketService_UdpSetUserData(OpcUa_Socket a_pSocket, OpcUa_Void* a_pvUserData) { OpcUa_InitializeStatus(OpcUa_Module_Socket, "UdpSetUserData"); OpcUa_GotoErrorIfArgumentNull(a_pSocket); OpcUa_ReferenceParameter(a_pvUserData); OpcUa_GotoErrorWithStatus(OpcUa_BadNotImplemented); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * Select usable socket. (maxfds ignored in win32) *===========================================================================*/ OpcUa_StatusCode OpcUa_P_RawSocket_Select( OpcUa_RawSocket a_MaxFds, OpcUa_P_Socket_Array* a_pFdSetRead, OpcUa_P_Socket_Array* a_pFdSetWrite, OpcUa_P_Socket_Array* a_pFdSetException, OpcUa_TimeVal* a_pTimeout) { int apiResult = 0; struct timeval timeout; OpcUa_InitializeStatus(OpcUa_Module_Socket, "P_Select"); OpcUa_ReferenceParameter(a_MaxFds); OpcUa_GotoErrorIfArgumentNull(a_pFdSetRead); OpcUa_GotoErrorIfArgumentNull(a_pFdSetWrite); OpcUa_GotoErrorIfArgumentNull(a_pFdSetException); timeout.tv_sec = a_pTimeout->uintSeconds; timeout.tv_usec = a_pTimeout->uintMicroSeconds; apiResult = select( 0, (fd_set*)a_pFdSetRead, (fd_set*)a_pFdSetWrite, (fd_set*)a_pFdSetException, &timeout); if(apiResult == OPCUA_P_SOCKET_SOCKETERROR) { apiResult = WSAGetLastError(); switch(apiResult) { case WSAENOTSOCK: { uStatus = OpcUa_BadInvalidArgument; break; } default: { uStatus = OpcUa_BadCommunicationError; } } } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * Get IP Address and Port Number of the Peer *===========================================================================*/ static OpcUa_StatusCode OpcUa_P_SocketService_UdpGetPeerInfo( OpcUa_Socket a_pSocket, OpcUa_CharA* a_achPeerInfoBuffer, OpcUa_UInt32 a_uiPeerInfoBufferSize) { OpcUa_InitializeStatus(OpcUa_Module_Socket, "UdpGetPeerInfo"); OpcUa_GotoErrorIfArgumentNull(a_pSocket); OpcUa_GotoErrorIfArgumentNull(a_achPeerInfoBuffer); OpcUa_ReferenceParameter(a_uiPeerInfoBufferSize); OpcUa_GotoErrorWithStatus(OpcUa_BadNotImplemented); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/* returns number of bytes written to the socket */ static OpcUa_Int32 OpcUa_P_SocketService_UdpWrite( OpcUa_Socket a_pSocket, OpcUa_Byte* a_pBuffer, OpcUa_UInt32 a_uBufferSize, OpcUa_Boolean a_bBlock) { OpcUa_InternalUdpSocket* pInternalSocket = (OpcUa_InternalUdpSocket*)a_pSocket; OpcUa_Int32 result; OpcUa_ReturnErrorIfNull(a_pSocket, OPCUA_SOCKET_ERROR); OpcUa_ReturnErrorIfNull(a_pBuffer, OPCUA_SOCKET_ERROR); OpcUa_ReferenceParameter(a_bBlock); result = OpcUa_P_RawSocket_Write (pInternalSocket->rawSocket, a_pBuffer, a_uBufferSize); return result; }
/*============================================================================ * OpcUa_TcpSecureChannel_ReleaseSecuritySet *===========================================================================*/ OpcUa_StatusCode OpcUa_TcpSecureChannel_ReleaseSecuritySet( OpcUa_SecureChannel* a_pSecureChannel, OpcUa_UInt32 a_uTokenId) { OpcUa_InitializeStatus(OpcUa_Module_SecureChannel, "ReleaseSecuritySet"); OpcUa_ReturnErrorIfArgumentNull(a_pSecureChannel); OpcUa_ReferenceParameter(a_uTokenId); OpcUa_Trace(OPCUA_TRACE_LEVEL_DEBUG, "ReleaseSecurityKeyset: Keyset for token %u released.\n", a_uTokenId); OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_PKI_NoSecurity_ExtractCertificateData *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_NoSecurity_ExtractCertificateData( OpcUa_ByteString* a_pCertificate, OpcUa_ByteString* a_pIssuer, OpcUa_ByteString* a_pSubject, OpcUa_ByteString* a_pSubjectUri, OpcUa_ByteString* a_pSubjectIP, OpcUa_ByteString* a_pSubjectDNS, OpcUa_ByteString* a_pCertThumbprint, OpcUa_UInt32* a_pSubjectHash, OpcUa_UInt32* a_pCertRawLength) { OpcUa_ReferenceParameter(a_pCertificate); OpcUa_ReferenceParameter(a_pIssuer); OpcUa_ReferenceParameter(a_pSubject); OpcUa_ReferenceParameter(a_pSubjectUri); OpcUa_ReferenceParameter(a_pSubjectIP); OpcUa_ReferenceParameter(a_pSubjectDNS); OpcUa_ReferenceParameter(a_pCertThumbprint); OpcUa_ReferenceParameter(a_pSubjectHash); OpcUa_ReferenceParameter(a_pCertRawLength); return OpcUa_BadNotSupported; }
/*===========================================================================* OpcUa_P_OpenSSL_RSA_Public_GetKeyLength *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Public_GetKeyLength( OpcUa_CryptoProvider* a_pProvider, OpcUa_Key a_publicKey, OpcUa_UInt32* a_pKeyLen) { EVP_PKEY* pPublicKey = OpcUa_Null; const unsigned char *pData; OpcUa_UInt32 uKeySize = 0; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Public_GetKeyLength"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_publicKey.Key.Data); OpcUa_ReturnErrorIfArgumentNull(a_pKeyLen); *a_pKeyLen = 0; if(a_publicKey.Type != OpcUa_Crypto_KeyType_Rsa_Public) { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument); } pData = a_publicKey.Key.Data; pPublicKey = d2i_PublicKey(EVP_PKEY_RSA, OpcUa_Null, &pData, a_publicKey.Key.Length); uKeySize = RSA_size(pPublicKey->pkey.rsa); *a_pKeyLen = uKeySize*8; EVP_PKEY_free(pPublicKey); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pPublicKey != OpcUa_Null) { EVP_PKEY_free(pPublicKey); } *a_pKeyLen = (OpcUa_UInt32)-1; OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_CertificateStore_Close *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_CloseCertificateStore( OpcUa_PKIProvider* a_pProvider, OpcUa_Void** a_ppCertificateStore) /* type depends on store implementation */ { OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_CloseCertificateStore"); OpcUa_ReferenceParameter(a_pProvider); if(*a_ppCertificateStore != OpcUa_Null) { X509_STORE_free((X509_STORE*)*a_ppCertificateStore); *a_ppCertificateStore = OpcUa_Null; } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_MemoryStream_Flush *===========================================================================*/ static OpcUa_StatusCode OpcUa_MemoryStream_Flush( OpcUa_OutputStream* ostrm, OpcUa_Boolean lastCall) { OpcUa_MemoryStream* handle = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_MemoryStream, "Flush"); OpcUa_ReturnErrorIfArgumentNull(ostrm); OpcUa_ReturnErrorIfInvalidStream(ostrm, Flush); OpcUa_ReferenceParameter(lastCall); handle = (OpcUa_MemoryStream*)ostrm->Handle; if(handle->Closed) { return OpcUa_BadInvalidState; } if(!OpcUa_Buffer_IsEmpty((OpcUa_Buffer *)handle->pBuffer)) { OpcUa_Byte* pData = OpcUa_Null; OpcUa_UInt32 uDataLength = 0; uStatus = OpcUa_Buffer_GetData(handle->pBuffer, &pData, &uDataLength); if (OpcUa_IsBad(uStatus)) { OpcUa_Trace(OPCUA_TRACE_LEVEL_ERROR, "Flush: FAILED with 0x%X\n", uStatus); OpcUa_GotoError; } } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/* SHA-2: 256 Bits output */ OpcUa_StatusCode OpcUa_P_OpenSSL_SHA2_256_Generate( OpcUa_CryptoProvider* a_pProvider, OpcUa_Byte* a_pData, OpcUa_UInt32 a_dataLen, OpcUa_Byte* a_pMessageDigest) { OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "SHA2_256_Generate"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pData); OpcUa_ReturnErrorIfArgumentNull(a_pMessageDigest); if(SHA256(a_pData, a_dataLen, a_pMessageDigest) == OpcUa_Null) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_RSA_Private_Decrypt *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Private_Decrypt( OpcUa_CryptoProvider* a_pProvider, OpcUa_Byte* a_pCipherText, OpcUa_UInt32 a_cipherTextLen, OpcUa_Key* a_privateKey, OpcUa_Int16 a_padding, OpcUa_Byte* a_pPlainText, OpcUa_UInt32* a_pPlainTextLen) { EVP_PKEY* pPrivateKey = OpcUa_Null; OpcUa_UInt32 keySize = 0; OpcUa_Int32 decryptedBytes = 0; OpcUa_UInt32 iCipherText = 0; /* OpcUa_UInt32 iPlainTextLen = 0; */ OpcUa_UInt32 decDataSize = 0; const char* sError = OpcUa_Null; const unsigned char *pData; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Private_Decrypt"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pCipherText); OpcUa_ReturnErrorIfArgumentNull(a_privateKey); OpcUa_ReturnErrorIfArgumentNull(a_privateKey->Key.Data); OpcUa_ReturnErrorIfArgumentNull(a_pPlainTextLen); *a_pPlainTextLen = 0; if(a_privateKey->Type != OpcUa_Crypto_KeyType_Rsa_Private) { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument); } pData = a_privateKey->Key.Data; pPrivateKey = d2i_PrivateKey(EVP_PKEY_RSA,OpcUa_Null, &pData, a_privateKey->Key.Length); if (pPrivateKey == OpcUa_Null) { long lErr = ERR_get_error(); char *szErr = ERR_error_string(lErr, 0); OpcUa_ReferenceParameter(szErr); return OpcUa_BadInvalidArgument; } keySize = RSA_size(pPrivateKey->pkey.rsa); if((a_cipherTextLen%keySize) != 0) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoError; } /* check padding type */ switch(a_padding) { case RSA_PKCS1_PADDING: { decDataSize = keySize - 11; break; } case RSA_PKCS1_OAEP_PADDING: { decDataSize = keySize - 42; break; } case RSA_NO_PADDING: { decDataSize = keySize; break; } default: { OpcUa_GotoErrorWithStatus(OpcUa_BadNotSupported); } } while(iCipherText < a_cipherTextLen) { if(a_pPlainText != OpcUa_Null) { decryptedBytes = RSA_private_decrypt( keySize, /* how much to decrypt */ a_pCipherText + iCipherText, /* what to decrypt */ a_pPlainText + (*a_pPlainTextLen), /* where to decrypt */ pPrivateKey->pkey.rsa, /* private key */ a_padding); /* padding mode */ /* goto error block, if decryption fails */ if(decryptedBytes == -1) { /* const char* serror = NULL; */ unsigned long error = ERR_get_error(); ERR_load_crypto_strings(); sError = ERR_reason_error_string(error); sError = ERR_func_error_string(error); sError = ERR_lib_error_string(error); uStatus = OpcUa_Bad; OpcUa_GotoError; } } else { decryptedBytes = decDataSize; } *a_pPlainTextLen = *a_pPlainTextLen + decryptedBytes; iCipherText = iCipherText + keySize; } EVP_PKEY_free(pPrivateKey); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pPrivateKey != OpcUa_Null) { EVP_PKEY_free(pPrivateKey); } *a_pPlainTextLen = (OpcUa_UInt32)-1; OpcUa_FinishErrorHandling; }
/*===========================================================================* OpcUa_P_OpenSSL_RSA_Public_Encrypt *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Public_Encrypt( OpcUa_CryptoProvider* a_pProvider, OpcUa_Byte* a_pPlainText, OpcUa_UInt32 a_plainTextLen, OpcUa_Key* a_publicKey, OpcUa_Int16 a_padding, OpcUa_Byte* a_pCipherText, OpcUa_UInt32* a_pCipherTextLen) { EVP_PKEY* pPublicKey = OpcUa_Null; OpcUa_UInt32 uKeySize = 0; OpcUa_UInt32 uEncryptedDataSize = 0; OpcUa_UInt32 uPlainTextPosition = 0; OpcUa_UInt32 uCipherTextPosition = 0; OpcUa_UInt32 uBytesToEncrypt = 0; OpcUa_Int32 iEncryptedBytes = 0; const unsigned char *pData; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Public_Encrypt"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_publicKey); OpcUa_ReturnErrorIfArgumentNull(a_publicKey->Key.Data); OpcUa_ReturnErrorIfArgumentNull(a_pCipherTextLen); *a_pCipherTextLen = 0; if((OpcUa_Int32)a_plainTextLen < 1) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } if(a_publicKey->Type != OpcUa_Crypto_KeyType_Rsa_Public) { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument); } pData = a_publicKey->Key.Data; pPublicKey = d2i_PublicKey(EVP_PKEY_RSA, OpcUa_Null, &pData, a_publicKey->Key.Length); if ( pPublicKey != OpcUa_Null ) { uKeySize = RSA_size(pPublicKey->pkey.rsa); } else { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument); } /* check padding type */ switch(a_padding) { case RSA_PKCS1_PADDING: { uEncryptedDataSize = uKeySize - 11; break; } case RSA_PKCS1_OAEP_PADDING: { uEncryptedDataSize = uKeySize - 42; break; } case RSA_NO_PADDING: { uEncryptedDataSize = uKeySize; break; } default: { OpcUa_GotoErrorWithStatus(OpcUa_BadNotSupported); } } if(a_plainTextLen < uEncryptedDataSize) { uBytesToEncrypt = a_plainTextLen; } else { uBytesToEncrypt = uEncryptedDataSize; } while(uPlainTextPosition < a_plainTextLen) { /* the last part could be smaller */ if((a_plainTextLen >= uEncryptedDataSize) && ((a_plainTextLen - uPlainTextPosition) < uEncryptedDataSize)) { uBytesToEncrypt = a_plainTextLen - uPlainTextPosition; } if((a_pCipherText != OpcUa_Null) && (a_pPlainText != OpcUa_Null)) { iEncryptedBytes = RSA_public_encrypt( uBytesToEncrypt, /* how much to encrypt */ a_pPlainText + uPlainTextPosition, /* what to encrypt */ a_pCipherText + uCipherTextPosition,/* where to encrypt */ pPublicKey->pkey.rsa, /* public key */ a_padding); /* padding mode */ if(iEncryptedBytes < 0) { const char* sError = OpcUa_Null; unsigned long error = 0; error = ERR_get_error(); ERR_load_crypto_strings(); sError = ERR_reason_error_string(error); sError = ERR_func_error_string(error); sError = ERR_lib_error_string(error); uStatus = OpcUa_Bad; OpcUa_GotoError; } } else { iEncryptedBytes = uKeySize; } *a_pCipherTextLen = *a_pCipherTextLen + iEncryptedBytes; uCipherTextPosition += uKeySize; uPlainTextPosition += uBytesToEncrypt; } EVP_PKEY_free(pPublicKey); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pPublicKey != OpcUa_Null) { EVP_PKEY_free(pPublicKey); } *a_pCipherTextLen = (OpcUa_UInt32)-1; OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_RSA_LoadPrivateKeyFromFile *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_LoadPrivateKeyFromFile( OpcUa_StringA a_privateKeyFile, OpcUa_P_FileFormat a_fileFormat, OpcUa_StringA a_password, /* optional: just needed encrypted PEM */ OpcUa_ByteString* a_pPrivateKey) { BIO* pPrivateKeyFile = OpcUa_Null; RSA* pRsaPrivateKey = OpcUa_Null; EVP_PKEY* pEvpKey = OpcUa_Null; unsigned char* pData; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_LoadPrivateKeyFromFile"); /* check parameters */ OpcUa_ReturnErrorIfArgumentNull(a_privateKeyFile); OpcUa_ReturnErrorIfArgumentNull(a_pPrivateKey); if(a_fileFormat == OpcUa_Crypto_Encoding_Invalid) { return OpcUa_BadInvalidArgument; } OpcUa_ReferenceParameter(a_password); /* open file */ pPrivateKeyFile = BIO_new_file((const char*)a_privateKeyFile, "rb"); OpcUa_ReturnErrorIfArgumentNull(pPrivateKeyFile); /* read and convert file */ switch(a_fileFormat) { case OpcUa_Crypto_Encoding_PEM: { /* read from file */ pEvpKey = PEM_read_bio_PrivateKey( pPrivateKeyFile, /* file */ NULL, /* key struct */ 0, /* password callback */ a_password); /* default passphrase or arbitrary handle */ OpcUa_GotoErrorIfNull(pEvpKey, OpcUa_Bad); break; } case OpcUa_Crypto_Encoding_PKCS12: { int iResult = 0; /* read from file. */ PKCS12* pPkcs12 = d2i_PKCS12_bio(pPrivateKeyFile, NULL); if (pPkcs12 == 0) { OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError); } /* parse the certificate. */ iResult = PKCS12_parse(pPkcs12, a_password, &pEvpKey, NULL, NULL); if (iResult == 0) { OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError); } /* free certificate. */ PKCS12_free(pPkcs12); pPkcs12 = NULL; break; } case OpcUa_Crypto_Encoding_DER: default: { uStatus = OpcUa_BadNotSupported; OpcUa_GotoError; } } /* convert to intermediary openssl struct */ pRsaPrivateKey = EVP_PKEY_get1_RSA(pEvpKey); EVP_PKEY_free(pEvpKey); OpcUa_GotoErrorIfNull(pRsaPrivateKey, OpcUa_Bad); /* get required length */ a_pPrivateKey->Length = i2d_RSAPrivateKey(pRsaPrivateKey, OpcUa_Null); OpcUa_GotoErrorIfTrue((a_pPrivateKey->Length <= 0), OpcUa_Bad); /* allocate target buffer */ a_pPrivateKey->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pPrivateKey->Length); OpcUa_GotoErrorIfAllocFailed(a_pPrivateKey->Data); /* do real conversion */ pData = a_pPrivateKey->Data; a_pPrivateKey->Length = i2d_RSAPrivateKey(pRsaPrivateKey, &pData); OpcUa_GotoErrorIfTrue((a_pPrivateKey->Length <= 0), OpcUa_Bad); RSA_free(pRsaPrivateKey); BIO_free(pPrivateKeyFile); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pEvpKey) { EVP_PKEY_free(pEvpKey); } if(a_pPrivateKey != OpcUa_Null) { if(a_pPrivateKey->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pPrivateKey->Data); a_pPrivateKey->Data = OpcUa_Null; a_pPrivateKey->Length = -1; } } if(pPrivateKeyFile != NULL) { BIO_free(pPrivateKeyFile); } if(pRsaPrivateKey != NULL) { RSA_free(pRsaPrivateKey); } OpcUa_FinishErrorHandling; }