#ifdef __WITH_DTLS__
#include "ocsecurityconfig.h"
#endif
+#ifdef __WITH_X509__
+#include "pki.h"
+#endif //__WITH_X509__
#ifdef __cplusplus
extern "C"
typedef void (*CAGetDTLSCredentialsHandler)(CADtlsPskCredsBlob_t **credInfo);
#endif //__WITH_DTLS__
+#ifdef __WITH_X509__
+/**
+ * Binary structure containing certificate chain and certificate credentials
+ * for this device.
+ */
+typedef struct
+{
+ // certificate message for DTLS
+ unsigned char certificateChain[MAX_CERT_MESSAGE_LEN];
+ // length of the certificate message
+ uint32_t certificateChainLen;
+ // number of certificates in certificate message
+ uint8_t chainLen;
+ // x component of EC public key
+ uint8_t rootPublicKeyX[PUBLIC_KEY_SIZE / 2];
+ // y component of EC public key
+ uint8_t rootPublicKeyY[PUBLIC_KEY_SIZE / 2];
+ // EC private key
+ uint8_t devicePrivateKey[PRIVATE_KEY_SIZE];
+
+} CADtlsCertCreds_t;
+
+/**
+ * @brief Callback function type for getting certificate credentials.
+ * @param credInfo [OUT] Certificate credentials info. Handler has to allocate new memory for
+ * credInfo which is then freed by CA
+ * @return NONE
+ */
+typedef void (*CAGetCertCredentialsHandler)(CADtlsCertCreds_t *credInfo);
+#endif //__WITH_X509__
+
/**
* Initialize the connectivity abstraction module.
* It will initialize adapters, thread pool and other modules based on the platform
CAResult_t CARegisterDTLSCredentialsHandler(CAGetDTLSCredentialsHandler GetDTLSCredentials);
#endif //__WITH_DTLS__
+#ifdef __WITH_X509__
+/**
+ * @brief Register callback to get DTLS Cert credentials.
+ * @param GetCertCredentials [IN] GetCert Credetials callback
+ * @return #CA_STATUS_OK
+ */
+CAResult_t CARegisterCertCredentialsHandler(CAGetCertCredentialsHandler GetCertCredentials);
+#endif //__WITH_X509__
+
/**
* Create an endpoint description.
* @param[in] flags how the adapter should be used.
#include "global.h"
#include <netdb.h>
+#ifdef __WITH_X509__
+#include "pki.h"
+#include "cainterface.h"
+#include "credresource.h"
+#undef VERIFY_SUCCESS
+#define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
+ {OIC_LOG_V(FATAL, NET_DTLS_TAG, "%s failed!!", #op); goto exit;} }
+#endif
+
/**
* @def NET_DTLS_TAG
* @brief Logging tag for module name
return CA_STATUS_OK;
}
+#ifdef __WITH_X509__
+static CADtlsCertCreds_t g_X509Cred = {{0}, 0, 0, {0}, {0}, {0}};
+
+static int g_IsX509Init = 0;
+
+int CAInitX509()
+{
+ OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CAInitX509");
+ g_IsX509Init = (OC_STACK_OK == GetDtlsCertCredentials(&g_X509Cred));
+
+ OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CAInitX509");
+ return !g_IsX509Init;
+}
+
+
+void CADeInitX509()
+{
+ g_IsX509Init = 0;
+}
+
+
+static int CAIsX509Active(struct dtls_context_t *ctx)
+{
+ (void)ctx;
+ return 0;
+}
+
+static int CAGetDeviceKey(struct dtls_context_t *ctx,
+ const session_t *session,
+ const dtls_ecc_key_t **result)
+{
+ OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceKey");
+ static dtls_ecc_key_t ecdsa_key = {DTLS_ECDH_CURVE_SECP256R1, NULL, NULL, NULL};
+
+ int ret = 1;
+ if (!g_IsX509Init)
+ {
+ VERIFY_SUCCESS(CAInitX509(), 0);
+ }
+
+ ecdsa_key.priv_key = g_X509Cred.devicePrivateKey;
+ *result = &ecdsa_key;
+
+ ret = 0;
+exit:
+ return ret;
+}
+
+static int
+CAGetDeviceCertificate(struct dtls_context_t *ctx,
+ const session_t *session,
+ const unsigned char **cert,
+ size_t *cert_size)
+{
+ OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetDeviceCertificate");
+ int ret = 1;
+ if (!g_IsX509Init)
+ {
+ VERIFY_SUCCESS(CAInitX509(), 0);
+ }
+ *cert = g_X509Cred.certificateChain;
+ *cert_size = g_X509Cred.certificateChainLen;
+#ifdef X509_DEBUG
+ ByteArray ownCert = {g_X509Cred.certificateChain, g_X509Cred.certificateChainLen};
+ PRINT_BYTE_ARRAY("OWN CERT: \n", ownCert);
+#endif
+
+ ret = 0;
+exit:
+ return ret;
+}
+/**
+ * @fn CAGetRootKey
+ * @brief Gets x and y components of Root Certificate Autority public key
+ *
+ * @return 0 on success otherwise a positive error value.
+ *
+ */
+static int CAGetRootKey(const unsigned char **ca_pub_x, const unsigned char **ca_pub_y)
+{
+ OIC_LOG(DEBUG, NET_DTLS_TAG, "CAGetRootKey");
+ int ret = 1;
+ if (!g_IsX509Init)
+ {
+ VERIFY_SUCCESS(CAInitX509(), 0);
+ }
+ *ca_pub_x = g_X509Cred.rootPublicKeyX;
+ *ca_pub_y = g_X509Cred.rootPublicKeyY;
+
+ ret = 0;
+exit:
+ return ret;
+}
+
+
+static int CAVerifyCertificate(struct dtls_context_t *ctx, const session_t *session,
+ const unsigned char *cert, size_t certLen,
+ const unsigned char *x, size_t xLen,
+ const unsigned char *y, size_t yLen)
+{
+ OIC_LOG(DEBUG, NET_DTLS_TAG, "Verify Certificate");
+
+ ByteArray crtChainDer[MAX_CHAIN_LEN];
+ CertificateX509 crtChain[MAX_CHAIN_LEN];
+
+ uint8_t chainLength;
+
+ int ret;
+ const unsigned char *ca_pub_x;
+ const unsigned char *ca_pub_y;
+ ByteArray certDerCode = BYTE_ARRAY_INITIALIZER;
+ ByteArray caPubKey = BYTE_ARRAY_INITIALIZER;
+ unsigned char ca_pub_key[PUBLIC_KEY_SIZE];
+
+ CAGetRootKey (&ca_pub_x, &ca_pub_y);
+
+ certDerCode.data = (uint8_t *)cert;
+ certDerCode.len = certLen;
+
+#ifdef X509_DEBUG
+ PRINT_BYTE_ARRAY("CERT :\n", certDerCode);
+#endif
+
+
+ caPubKey.len = PUBLIC_KEY_SIZE;
+ caPubKey.data = ca_pub_key;
+
+ memcpy(caPubKey.data, ca_pub_x, PUBLIC_KEY_SIZE / 2);
+ memcpy(caPubKey.data + PUBLIC_KEY_SIZE / 2, ca_pub_y, PUBLIC_KEY_SIZE / 2);
+
+ ret = (int) LoadCertificateChain (certDerCode, crtChainDer, &chainLength);
+ VERIFY_SUCCESS(ret, PKI_SUCCESS);
+ ret = (int) ParseCertificateChain (crtChainDer, crtChain, chainLength );
+ VERIFY_SUCCESS(ret, PKI_SUCCESS);
+ ret = (int) CheckCertificateChain (crtChain, chainLength, caPubKey);
+ VERIFY_SUCCESS(ret, PKI_SUCCESS);
+
+ INC_BYTE_ARRAY(crtChain[0].pubKey, 2);
+
+ memcpy(x, crtChain[0].pubKey.data, xLen);
+ memcpy(y, crtChain[0].pubKey.data + PUBLIC_KEY_SIZE / 2, yLen);
+
+
+ if (NULL != ctx->peers && DTLS_SERVER == ctx->peers->role )
+ {
+ stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
+ char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
+ uint16_t port = 0;
+ CAConvertAddrToName(&(addrInfo->addr.st), peerAddr, &port);
+
+ CAResult_t result = CAAddIdToPeerInfoList(peerAddr, port,
+ crtChain[0].subject.data + crtChain[0].subject.len - sizeof(OicUuid_t), sizeof(OicUuid_t));
+ if (CA_STATUS_OK != result )
+ {
+ OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
+ }
+ }
+
+
+exit:
+ if (ret != 0) OIC_LOG(DEBUG, NET_DTLS_TAG, "Certificate verification FAILED\n");
+ else OIC_LOG(DEBUG, NET_DTLS_TAG, "Certificate verification SUCCESS\n");
+ return -ret;
+}
+
+#endif
+
+
+
+
CAResult_t CAAdapterNetDtlsInit()
{
OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
g_caDtlsContext->callbacks.write = CASendSecureData;
g_caDtlsContext->callbacks.read = CAReadDecryptedPayload;
g_caDtlsContext->callbacks.event = CAHandleSecureEvent;
- g_caDtlsContext->callbacks.get_psk_info = CAGetPskCredentials;
+#ifdef __WITH_X509__
+ CAInitX509();
+ if (g_IsX509Init == 0)
+#endif //__WITH_X509__
+ g_caDtlsContext->callbacks.get_psk_info = CAGetPskCredentials;
+#ifdef __WITH_X509__
+ g_caDtlsContext->callbacks.get_x509_key = CAGetDeviceKey;
+ g_caDtlsContext->callbacks.verify_x509_cert = CAVerifyCertificate;
+ g_caDtlsContext->callbacks.get_x509_cert = CAGetDeviceCertificate;
+ g_caDtlsContext->callbacks.is_x509_active = CAIsX509Active;
+#endif //__WITH_X509__*
dtls_set_handler(g_caDtlsContext->dtlsContext, &(g_caDtlsContext->callbacks));
ca_mutex_unlock(g_dtlsContextMutex);
OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");