/*============================================================================ * 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_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; }
/* internal function */ OpcUa_P_OpenSSL_PSHA256_Ctx* OpcUa_P_OpenSSL_PSHA256_Context_Create( OpcUa_Byte* a_pSecret, OpcUa_UInt32 a_secretLen, OpcUa_Byte* a_pSeed, OpcUa_Int32 a_seedLen) { OpcUa_P_OpenSSL_PSHA256_Ctx* pCtx; OpcUa_Int size; if(a_pSecret == OpcUa_Null || a_pSeed == OpcUa_Null) return OpcUa_Null; pCtx = OpcUa_Null; size = sizeof(OpcUa_P_OpenSSL_PSHA256_Ctx) + a_secretLen + a_seedLen; pCtx = (OpcUa_P_OpenSSL_PSHA256_Ctx*) OpcUa_P_Memory_Alloc(size); if (pCtx == OpcUa_Null) return OpcUa_Null; pCtx->secret_len = a_secretLen; pCtx->seed_len = a_seedLen; OpcUa_P_Memory_MemCpy(OpcUa_P_OpenSSL_PSHA256_SECRET(pCtx), a_secretLen, a_pSecret, a_secretLen); OpcUa_P_Memory_MemCpy(OpcUa_P_OpenSSL_PSHA256_SEED(pCtx), a_seedLen, a_pSeed, a_seedLen); /* A(0) = seed */ /* A(i) = HMAC_SHA256(secret, A(i-1)) */ /* Calculate A(1) = HMAC_SHA256(secret, seed) */ HMAC(EVP_sha256(), a_pSecret, a_secretLen, a_pSeed, a_seedLen, (unsigned char*)pCtx->A, (unsigned int*)OpcUa_Null); if(pCtx == OpcUa_Null) return OpcUa_Null; return pCtx; }
/*============================================================================ * OpcUa_P_OpenSSL_X509_GetCertificateThumbprint *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_X509_GetCertificateThumbprint( OpcUa_CryptoProvider* a_pProvider, OpcUa_ByteString* a_pCertificate, OpcUa_ByteString* a_pCertificateThumbprint) { X509* pX509Certificate = OpcUa_Null; const unsigned char* pTemp = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_GetCertificateThumbprint"); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate->Data); OpcUa_ReturnErrorIfArgumentNull(a_pCertificateThumbprint); /* SHA-1 produces 20 bytes */ a_pCertificateThumbprint->Length = sizeof(pX509Certificate->sha1_hash); if(a_pCertificateThumbprint->Data == OpcUa_Null) { OpcUa_ReturnStatusCode; } /* 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); } /* update pX509Certificate->sha1_hash */ X509_check_purpose(pX509Certificate, -1, 0); uStatus = OpcUa_P_Memory_MemCpy(a_pCertificateThumbprint->Data, a_pCertificateThumbprint->Length, pX509Certificate->sha1_hash, sizeof(pX509Certificate->sha1_hash)); X509_free(pX509Certificate); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_ParseUrl *===========================================================================*/ OpcUa_StatusCode OpcUa_P_ParseUrl( OpcUa_StringA a_psUrl, OpcUa_StringA* a_psIpAdress, OpcUa_UInt16* a_puPort) { OpcUa_UInt32 uUrlLength = 0; OpcUa_StringA sHostName = OpcUa_Null; OpcUa_UInt32 uHostNameLength = 0; OpcUa_CharA* pcCursor = OpcUa_Null; OpcUa_Int nIndex1 = 0; OpcUa_Int nIpStart = 0; struct hostent* pHostEnt = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_Utilities, "P_ParseUrl"); OpcUa_ReturnErrorIfArgumentNull(a_psUrl); OpcUa_ReturnErrorIfArgumentNull(a_psIpAdress); OpcUa_ReturnErrorIfArgumentNull(a_puPort); *a_psIpAdress = OpcUa_Null; uUrlLength = (OpcUa_UInt32)strlen(a_psUrl); /* check for // (end of protocol header) */ pcCursor = strstr(a_psUrl, "//"); if(pcCursor != OpcUa_Null) { /* begin of host address */ pcCursor += 2; nIndex1 = (OpcUa_Int)(pcCursor - a_psUrl); } else { uStatus = OpcUa_BadSyntaxError; OpcUa_ReturnStatusCode; } /* skip protocol prefix and store beginning of ip adress */ nIpStart = nIndex1; /* skip host address */ while( a_psUrl[nIndex1] != ':' && a_psUrl[nIndex1] != '/' && a_psUrl[nIndex1] != 0 && nIndex1 < (OpcUa_Int32)uUrlLength) { nIndex1++; } uHostNameLength = nIndex1 - nIpStart; sHostName = (OpcUa_StringA)malloc(uHostNameLength + 1); if(sHostName == NULL) { return OpcUa_BadOutOfMemory; } memcpy(sHostName, &a_psUrl[nIpStart], uHostNameLength); sHostName[uHostNameLength] = '\0'; pHostEnt = gethostbyname(sHostName); free(sHostName); if(pHostEnt == NULL) { /* hostname could not be resolved */ return OpcUa_BadHostUnknown; } nIpStart = 0; *a_psIpAdress = (OpcUa_StringA)OpcUa_P_Memory_Alloc(16); memset(*a_psIpAdress, 0, 16); #if OPCUA_USE_SAFE_FUNCTIONS nIpStart += sprintf_s(&(*a_psIpAdress)[0], 16,"%u", (unsigned char)(*((*pHostEnt).h_addr_list))[0]); (*a_psIpAdress)[nIpStart++] = '.'; nIpStart += sprintf_s(&(*a_psIpAdress)[nIpStart], 12,"%u", (unsigned char)(*((*pHostEnt).h_addr_list))[1]); (*a_psIpAdress)[nIpStart++] = '.'; nIpStart += sprintf_s(&(*a_psIpAdress)[nIpStart], 8,"%u", (unsigned char)(*((*pHostEnt).h_addr_list))[2]); (*a_psIpAdress)[nIpStart++] = '.'; nIpStart += sprintf_s(&(*a_psIpAdress)[nIpStart], 4,"%u", (unsigned char)(*((*pHostEnt).h_addr_list))[3]); #else /* OPCUA_USE_SAFE_FUNCTIONS */ nIpStart += sprintf(&(*a_psIpAdress)[0], "%u", (unsigned char)(*((*pHostEnt).h_addr_list))[0]); (*a_psIpAdress)[nIpStart++] = '.'; nIpStart += sprintf(&(*a_psIpAdress)[nIpStart], "%u", (unsigned char)(*((*pHostEnt).h_addr_list))[1]); (*a_psIpAdress)[nIpStart++] = '.'; nIpStart += sprintf(&(*a_psIpAdress)[nIpStart], "%u", (unsigned char)(*((*pHostEnt).h_addr_list))[2]); (*a_psIpAdress)[nIpStart++] = '.'; nIpStart += sprintf(&(*a_psIpAdress)[nIpStart], "%u", (unsigned char)(*((*pHostEnt).h_addr_list))[3]); #endif /* OPCUA_USE_SAFE_FUNCTIONS */ /* scan port */ if(a_psUrl[nIndex1] == ':') { OpcUa_Int nIndex2 = 0; OpcUa_CharA* sPort = OpcUa_Null; OpcUa_CharA sBuffer[MAX_PORT_LENGTH]; /* skip delimiter */ nIndex1++; /* store beginning of port */ sPort = &a_psUrl[nIndex1]; /* search for end of port */ while( a_psUrl[nIndex1] != '/' && a_psUrl[nIndex1] != 0 && nIndex2 < 6) { nIndex1++; nIndex2++; } /* convert port */ OpcUa_P_Memory_MemCpy(sBuffer, MAX_PORT_LENGTH-1, sPort, nIndex2); sBuffer[nIndex2] = 0; *a_puPort = (OpcUa_UInt16)OpcUa_P_CharAToInt(sBuffer); } else { /* return default port */ if (strncmp(a_psUrl, "http:", 5) != 0) { *a_puPort = OPCUA_TCP_DEFAULT_PORT; } else { *a_puPort = OPCUA_HTTP_DEFAULT_PORT; } } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/** @brief Extracts data from a certificate store object. @param pCertificate [in] The certificate to examine. @param pIssuer [out, optional] The issuer name of the certificate. @param pSubject [out, optional] The subject name of the certificate. @param pSubjectUri [out, optional] The subject's URI of the certificate. @param pSubjectIP [out, optional] The subject's IP of the certificate. @param pSubjectDNS [out, optional] The subject's DNS name of the certificate. @param pCertThumbprint [out, optional] The thumbprint of the certificate. @param pSubjectHash [out, optional] The hash code of the certificate. @param pCertRawLength [out, optional] The length of the DER encoded data. can be smaller than the total length of pCertificate in case of chain certificate or garbage follow. */ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_ExtractCertificateData( OpcUa_ByteString* a_pCertificate, OpcUa_ByteString* a_pIssuer, OpcUa_ByteString* a_pSubject, OpcUa_ByteString* a_pSubjectUri, OpcUa_ByteString* a_pSubjectIP, OpcUa_ByteString* a_pSubjectDNS, OpcUa_ByteString* a_pCertThumbprint, OpcUa_UInt32* a_pSubjectHash, OpcUa_UInt32* a_pCertRawLength) { X509* pX509Cert = OpcUa_Null; char* pName = OpcUa_Null; GENERAL_NAMES* pNames = OpcUa_Null; const unsigned char* p; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_ExtractCertificateData"); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); if(a_pIssuer != OpcUa_Null) { a_pIssuer->Data = OpcUa_Null; a_pIssuer->Length = 0; } if(a_pSubject != OpcUa_Null) { a_pSubject->Data = OpcUa_Null; a_pSubject->Length = 0; } if(a_pSubjectUri != OpcUa_Null) { a_pSubjectUri->Data = OpcUa_Null; a_pSubjectUri->Length = 0; } if(a_pSubjectIP != OpcUa_Null) { a_pSubjectIP->Data = OpcUa_Null; a_pSubjectIP->Length = 0; } if(a_pSubjectDNS != OpcUa_Null) { a_pSubjectDNS->Data = OpcUa_Null; a_pSubjectDNS->Length = 0; } if(a_pCertThumbprint != OpcUa_Null) { a_pCertThumbprint->Data = OpcUa_Null; a_pCertThumbprint->Length = 0; } if(a_pSubjectHash != OpcUa_Null) { *a_pSubjectHash = 0; } if(a_pCertRawLength != OpcUa_Null) { *a_pCertRawLength = 0; } /* convert openssl X509 certificate to DER encoded bytestring certificate */ p = a_pCertificate->Data; if(!(pX509Cert = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Length))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(a_pIssuer != OpcUa_Null) { pName = X509_NAME_oneline(X509_get_issuer_name(pX509Cert), NULL, 0); OpcUa_GotoErrorIfAllocFailed(pName); a_pIssuer->Length = strlen(pName)+1; a_pIssuer->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pIssuer->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pIssuer->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pIssuer->Data, a_pIssuer->Length, pName, a_pIssuer->Length); OpcUa_GotoErrorIfBad(uStatus); OPENSSL_free(pName); pName = OpcUa_Null; } if(a_pSubject != OpcUa_Null) { pName = X509_NAME_oneline(X509_get_subject_name(pX509Cert), NULL, 0); OpcUa_GotoErrorIfAllocFailed(pName); a_pSubject->Length = strlen(pName)+1; a_pSubject->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubject->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pSubject->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pSubject->Data, a_pSubject->Length, pName, a_pSubject->Length); OpcUa_GotoErrorIfBad(uStatus); OPENSSL_free(pName); pName = OpcUa_Null; } if(a_pSubjectUri != OpcUa_Null || a_pSubjectIP != OpcUa_Null || a_pSubjectDNS != OpcUa_Null) { pNames = X509_get_ext_d2i(pX509Cert, NID_subject_alt_name, OpcUa_Null, OpcUa_Null); if (pNames != OpcUa_Null) { int num; for (num = 0; num < sk_GENERAL_NAME_num(pNames); num++) { GENERAL_NAME *value = sk_GENERAL_NAME_value(pNames, num); switch (value->type) { case GEN_URI: if (a_pSubjectUri != OpcUa_Null && a_pSubjectUri->Data == OpcUa_Null) { a_pSubjectUri->Length = value->d.ia5->length+1; a_pSubjectUri->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubjectUri->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pSubjectUri->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pSubjectUri->Data, a_pSubjectUri->Length, value->d.ia5->data, a_pSubjectUri->Length); OpcUa_GotoErrorIfBad(uStatus); } break; case GEN_IPADD: if (a_pSubjectIP != OpcUa_Null && a_pSubjectIP->Data == OpcUa_Null) { a_pSubjectIP->Length = value->d.ip->length; a_pSubjectIP->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubjectIP->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pSubjectIP->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pSubjectIP->Data, a_pSubjectIP->Length, value->d.ip->data, a_pSubjectIP->Length); OpcUa_GotoErrorIfBad(uStatus); } break; case GEN_DNS: if (a_pSubjectDNS != OpcUa_Null && a_pSubjectDNS->Data == OpcUa_Null) { a_pSubjectDNS->Length = value->d.ia5->length+1; a_pSubjectDNS->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubjectDNS->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pSubjectDNS->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pSubjectDNS->Data, a_pSubjectDNS->Length, value->d.ia5->data, a_pSubjectDNS->Length); OpcUa_GotoErrorIfBad(uStatus); } break; } } sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free); pNames = OpcUa_Null; } } if(a_pCertThumbprint != OpcUa_Null) { /* update pX509Cert->sha1_hash */ X509_check_purpose(pX509Cert, -1, 0); a_pCertThumbprint->Length = sizeof(pX509Cert->sha1_hash); a_pCertThumbprint->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertThumbprint->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pCertThumbprint->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pCertThumbprint->Data, a_pCertThumbprint->Length, pX509Cert->sha1_hash, a_pCertThumbprint->Length); OpcUa_GotoErrorIfBad(uStatus); } if(a_pSubjectHash != OpcUa_Null) { *a_pSubjectHash = X509_NAME_hash(X509_get_subject_name(pX509Cert)); } if(a_pCertRawLength != OpcUa_Null) { *a_pCertRawLength = (OpcUa_UInt32)(p - a_pCertificate->Data); } X509_free(pX509Cert); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(a_pIssuer != OpcUa_Null && a_pIssuer->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pIssuer->Data); a_pIssuer->Data = OpcUa_Null; a_pIssuer->Length = 0; } if(a_pSubject != OpcUa_Null && a_pSubject->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pSubject->Data); a_pSubject->Data = OpcUa_Null; a_pSubject->Length = 0; } if(a_pSubjectUri != OpcUa_Null && a_pSubjectUri->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pSubjectUri->Data); a_pSubjectUri->Data = OpcUa_Null; a_pSubjectUri->Length = 0; } if(a_pSubjectIP != OpcUa_Null && a_pSubjectIP->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pSubjectIP->Data); a_pSubjectIP->Data = OpcUa_Null; a_pSubjectIP->Length = 0; } if(a_pSubjectDNS != OpcUa_Null && a_pSubjectDNS->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pSubjectDNS->Data); a_pSubjectDNS->Data = OpcUa_Null; a_pSubjectDNS->Length = 0; } if(a_pCertThumbprint != OpcUa_Null && a_pCertThumbprint->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pCertThumbprint->Data); a_pCertThumbprint->Data = OpcUa_Null; a_pCertThumbprint->Length = 0; } if (pName != OpcUa_Null) { OPENSSL_free(pName); } if (pNames != OpcUa_Null) { sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free); } if(pX509Cert != OpcUa_Null) { X509_free(pX509Cert); } OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_Random_Key_PSHA256_Derive *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_Random_Key_PSHA256_Derive( OpcUa_CryptoProvider* a_pProvider, OpcUa_ByteString a_secret, /* clientnonce | servernonce, servernonce | clientnonce */ OpcUa_ByteString a_seed, OpcUa_Int32 a_keyLen, /* output len */ OpcUa_Key* a_pKey) { OpcUa_P_OpenSSL_PSHA256_Ctx*pCtx = OpcUa_Null; OpcUa_Byte* pBuffer = OpcUa_Null; OpcUa_Int bufferlength; OpcUa_Int i; OpcUa_Int iterations; OpcUa_CryptoProviderConfig* pConfig = OpcUa_Null; OpcUa_Int32 keyLen = 0; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "Random_Key_PSHA256_Derive"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_secret.Data); OpcUa_ReturnErrorIfArgumentNull(a_seed.Data); OpcUa_ReturnErrorIfArgumentNull(a_pKey); keyLen = a_keyLen; if(keyLen < 0) { if(a_pProvider->Handle != OpcUa_Null) { /* get default configuration */ pConfig = (OpcUa_CryptoProviderConfig*)a_pProvider->Handle; keyLen = pConfig->SymmetricKeyLength; } else { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } } else if(keyLen > MAX_DERIVED_OUTPUT_LEN) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } if(a_pKey->Key.Data == OpcUa_Null) { a_pKey->Key.Length = keyLen; OpcUa_ReturnStatusCode; } a_pKey->Type = OpcUa_Crypto_KeyType_Random; /** start creating key **/ pCtx = (OpcUa_P_OpenSSL_PSHA256_Ctx*)OpcUa_Null; iterations = keyLen/32 + (keyLen%32?1:0); bufferlength = iterations*32; pBuffer = (OpcUa_Byte *)OpcUa_P_Memory_Alloc(bufferlength * sizeof(OpcUa_Byte)); pCtx = OpcUa_P_OpenSSL_PSHA256_Context_Create(a_secret.Data, a_secret.Length, a_seed.Data, a_seed.Length); for(i=0; i<iterations; i++) { /* SHA256 produces 32 Bytes of output for every iteration */ uStatus = OpcUa_P_OpenSSL_PSHA256_Hash_Generate(pCtx, pBuffer + (i*32)); OpcUa_GotoErrorIfBad(uStatus); } OpcUa_P_Memory_MemCpy(a_pKey->Key.Data, a_pKey->Key.Length, pBuffer, keyLen); if(pCtx != OpcUa_Null) { OpcUa_P_Memory_Free(pCtx); pCtx = OpcUa_Null; } if(pBuffer != OpcUa_Null) { OpcUa_P_Memory_Free(pBuffer); pBuffer = OpcUa_Null; } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pCtx != OpcUa_Null) { OpcUa_P_Memory_Free(pCtx); pCtx = OpcUa_Null; } if(pBuffer != OpcUa_Null) { OpcUa_P_Memory_Free(pBuffer); pBuffer = OpcUa_Null; } OpcUa_FinishErrorHandling; }