terence zhang / Mbed OS mbed-os-example-wakaama

Dependencies:   C12832 LM75B

Revision:
15:d0f20339c1ad
Parent:
14:ec9e195830ff
--- a/share/object_security.c	Sat May 06 11:21:27 2017 +0000
+++ b/share/object_security.c	Sun May 07 03:00:16 2017 +0000
@@ -1,6 +1,6 @@
 /*******************************************************************************
  *
- * Copyright (c) 2013, 2014, 2015 Intel Corporation and others.
+ * Copyright (c) 2013, 2014 Intel Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -46,13 +46,37 @@
 #include <string.h>
 #include <stdio.h>
 
+#define LWM2M_SECURITY_URI_ID                 0
+#define LWM2M_SECURITY_BOOTSTRAP_ID           1
+#define LWM2M_SECURITY_MODE_ID            2
+#define LWM2M_SECURITY_PUBLIC_KEY_ID          3
+#define LWM2M_SECURITY_SERVER_PUBLIC_KEY_ID   4
+#define LWM2M_SECURITY_SECRET_KEY_ID          5
+#define LWM2M_SECURITY_SMS_SECURITY_ID        6
+#define LWM2M_SECURITY_SMS_KEY_PARAM_ID       7
+#define LWM2M_SECURITY_SMS_SECRET_KEY_ID      8
+#define LWM2M_SECURITY_SMS_SERVER_NUMBER_ID   9
+#define LWM2M_SECURITY_SHORT_SERVER_ID        10
+#define LWM2M_SECURITY_HOLD_OFF_ID            11
 
 typedef struct _security_instance_
 {
     struct _security_instance_ * next;        // matches lwm2m_list_t::next
     uint16_t                     instanceId;  // matches lwm2m_list_t::id
     char *                       uri;
-    bool                         isBootstrap;
+    bool                         isBootstrap;    
+    uint8_t                      securityMode;
+    char *                       publicIdentity;
+    uint16_t                     publicIdLen;
+    char *                       serverPublicKey;
+    uint16_t                     serverPublicKeyLen;
+    char *                       secretKey;
+    uint16_t                     secretKeyLen;
+    uint8_t                      smsSecurityMode;
+    char *                       smsParams; // SMS binding key parameters
+    uint16_t                     smsParamsLen;
+    char *                       smsSecret; // SMS binding secret key
+    uint16_t                     smsSecretLen;
     uint16_t                     shortID;
     uint32_t                     clientHoldOffTime;
 } security_instance_t;
@@ -60,7 +84,6 @@
 static uint8_t prv_get_value(lwm2m_data_t * dataP,
                              security_instance_t * targetP)
 {
-
     switch (dataP->id)
     {
     case LWM2M_SECURITY_URI_ID:
@@ -72,54 +95,31 @@
         return COAP_205_CONTENT;
 
     case LWM2M_SECURITY_SECURITY_ID:
-        lwm2m_data_encode_int(LWM2M_SECURITY_MODE_NONE, dataP);
+        lwm2m_data_encode_int(targetP->securityMode, dataP);
         return COAP_205_CONTENT;
 
     case LWM2M_SECURITY_PUBLIC_KEY_ID:
-        // Here we return an opaque of 1 byte containing 0
-        {
-            uint8_t value = 0;
-
-            lwm2m_data_encode_opaque(&value, 1, dataP);
-        }
+        lwm2m_data_encode_opaque((uint8_t*)targetP->publicIdentity, targetP->publicIdLen, dataP);
         return COAP_205_CONTENT;
 
     case LWM2M_SECURITY_SERVER_PUBLIC_KEY_ID:
-        // Here we return an opaque of 1 byte containing 0
-        {
-            uint8_t value = 0;
-
-            lwm2m_data_encode_opaque(&value, 1, dataP);
-        }
+        lwm2m_data_encode_opaque((uint8_t*)targetP->serverPublicKey, targetP->serverPublicKeyLen, dataP);
         return COAP_205_CONTENT;
 
     case LWM2M_SECURITY_SECRET_KEY_ID:
-        // Here we return an opaque of 1 byte containing 0
-        {
-            uint8_t value = 0;
-
-            lwm2m_data_encode_opaque(&value, 1, dataP);
-        }
+        lwm2m_data_encode_opaque((uint8_t*)targetP->secretKey, targetP->secretKeyLen, dataP);
         return COAP_205_CONTENT;
 
     case LWM2M_SECURITY_SMS_SECURITY_ID:
-        lwm2m_data_encode_int(LWM2M_SECURITY_MODE_NONE, dataP);
+        lwm2m_data_encode_int(targetP->smsSecurityMode, dataP);
         return COAP_205_CONTENT;
 
     case LWM2M_SECURITY_SMS_KEY_PARAM_ID:
-        // Here we return an opaque of 6 bytes containing a buggy value
-        {
-            char * value = "12345";
-            lwm2m_data_encode_opaque((uint8_t *)value, 6, dataP);
-        }
+        lwm2m_data_encode_opaque((uint8_t*)targetP->smsParams, targetP->smsParamsLen, dataP);
         return COAP_205_CONTENT;
 
     case LWM2M_SECURITY_SMS_SECRET_KEY_ID:
-        // Here we return an opaque of 32 bytes containing a buggy value
-        {
-            char * value = "1234567890abcdefghijklmnopqrstu";
-            lwm2m_data_encode_opaque((uint8_t *)value, 32, dataP);
-        }
+        lwm2m_data_encode_opaque((uint8_t*)targetP->smsSecret, targetP->smsSecretLen, dataP);
         return COAP_205_CONTENT;
 
     case LWM2M_SECURITY_SMS_SERVER_NUMBER_ID:
@@ -187,7 +187,320 @@
     return result;
 }
 
-lwm2m_object_t * get_security_object()
+#ifdef LWM2M_BOOTSTRAP
+
+static uint8_t prv_security_write(uint16_t instanceId,
+                                  int numData,
+                                  lwm2m_data_t * dataArray,
+                                  lwm2m_object_t * objectP)
+{
+    security_instance_t * targetP;
+    int i;
+    uint8_t result = COAP_204_CHANGED;
+
+    targetP = (security_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId);
+    if (NULL == targetP)
+    {
+        return COAP_404_NOT_FOUND;
+    }
+
+    i = 0;
+    do {
+        switch (dataArray[i].id)
+        {
+        case LWM2M_SECURITY_URI_ID:
+            if (targetP->uri != NULL) lwm2m_free(targetP->uri);
+            targetP->uri = (char *)lwm2m_malloc(dataArray[i].value.asBuffer.length + 1);
+            memset(targetP->uri, 0, dataArray[i].value.asBuffer.length + 1);
+            if (targetP->uri != NULL)
+            {
+                strncpy(targetP->uri, (char*)dataArray[i].value.asBuffer.buffer, dataArray[i].value.asBuffer.length);
+                result = COAP_204_CHANGED;
+            }
+            else
+            {
+                result = COAP_500_INTERNAL_SERVER_ERROR;
+            }
+            break;
+
+        case LWM2M_SECURITY_BOOTSTRAP_ID:
+            if (1 == lwm2m_data_decode_bool(dataArray + i, &(targetP->isBootstrap)))
+            {
+                result = COAP_204_CHANGED;
+            }
+            else
+            {
+                result = COAP_400_BAD_REQUEST;
+            }
+            break;
+
+        case LWM2M_SECURITY_SECURITY_ID:
+        {
+            int64_t value;
+
+            if (1 == lwm2m_data_decode_int(dataArray + i, &value))
+            {
+                if (value >= 0 && value <= 3)
+                {
+                    targetP->securityMode = value;
+                    result = COAP_204_CHANGED;
+                }
+                else
+                {
+                    result = COAP_406_NOT_ACCEPTABLE;
+                }
+            }
+            else
+            {
+                result = COAP_400_BAD_REQUEST;
+            }
+        }
+        break;
+        case LWM2M_SECURITY_PUBLIC_KEY_ID:
+            if (targetP->publicIdentity != NULL) lwm2m_free(targetP->publicIdentity);
+            targetP->publicIdentity = (char *)lwm2m_malloc(dataArray[i].value.asBuffer.length +1);
+            memset(targetP->publicIdentity, 0, dataArray[i].value.asBuffer.length + 1);
+            if (targetP->publicIdentity != NULL)
+            {
+                memcpy(targetP->publicIdentity, (char*)dataArray[i].value.asBuffer.buffer, dataArray[i].value.asBuffer.length);
+                targetP->publicIdLen = dataArray[i].value.asBuffer.length;
+                result = COAP_204_CHANGED;
+            }
+            else
+            {
+                result = COAP_500_INTERNAL_SERVER_ERROR;
+            }
+            break;
+
+        case LWM2M_SECURITY_SERVER_PUBLIC_KEY_ID:
+            if (targetP->serverPublicKey != NULL) lwm2m_free(targetP->serverPublicKey);
+            targetP->serverPublicKey = (char *)lwm2m_malloc(dataArray[i].value.asBuffer.length +1);
+            memset(targetP->serverPublicKey, 0, dataArray[i].value.asBuffer.length + 1);
+            if (targetP->serverPublicKey != NULL)
+            {
+                memcpy(targetP->serverPublicKey, (char*)dataArray[i].value.asBuffer.buffer, dataArray[i].value.asBuffer.length);
+                targetP->serverPublicKeyLen = dataArray[i].value.asBuffer.length;
+                result = COAP_204_CHANGED;
+            }
+            else
+            {
+                result = COAP_500_INTERNAL_SERVER_ERROR;
+            }
+            break;
+
+        case LWM2M_SECURITY_SECRET_KEY_ID:
+            if (targetP->secretKey != NULL) lwm2m_free(targetP->secretKey);
+            targetP->secretKey = (char *)lwm2m_malloc(dataArray[i].value.asBuffer.length +1);
+            memset(targetP->secretKey, 0, dataArray[i].value.asBuffer.length + 1);
+            if (targetP->secretKey != NULL)
+            {
+                memcpy(targetP->secretKey, (char*)dataArray[i].value.asBuffer.buffer, dataArray[i].value.asBuffer.length);
+                targetP->secretKeyLen = dataArray[i].value.asBuffer.length;
+                result = COAP_204_CHANGED;
+            }
+            else
+            {
+                result = COAP_500_INTERNAL_SERVER_ERROR;
+            }
+            break;
+
+        case LWM2M_SECURITY_SMS_SECURITY_ID:
+            // Let just ignore this
+            result = COAP_204_CHANGED;
+            break;
+
+        case LWM2M_SECURITY_SMS_KEY_PARAM_ID:
+            // Let just ignore this
+            result = COAP_204_CHANGED;
+            break;
+
+        case LWM2M_SECURITY_SMS_SECRET_KEY_ID:
+            // Let just ignore this
+            result = COAP_204_CHANGED;
+            break;
+
+        case LWM2M_SECURITY_SMS_SERVER_NUMBER_ID:
+            // Let just ignore this
+            result = COAP_204_CHANGED;
+            break;
+
+        case LWM2M_SECURITY_SHORT_SERVER_ID:
+        {
+            int64_t value;
+
+            if (1 == lwm2m_data_decode_int(dataArray + i, &value))
+            {
+                if (value >= 0 && value <= 0xFFFF)
+                {
+                    targetP->shortID = value;
+                    result = COAP_204_CHANGED;
+                }
+                else
+                {
+                    result = COAP_406_NOT_ACCEPTABLE;
+                }
+            }
+            else
+            {
+                result = COAP_400_BAD_REQUEST;
+            }
+        }
+        break;
+
+        case LWM2M_SECURITY_HOLD_OFF_ID:
+        {
+            int64_t value;
+
+            if (1 == lwm2m_data_decode_int(dataArray + i, &value))
+            {
+                if (value >= 0 && value <= 0xFFFF)
+                {
+                    targetP->clientHoldOffTime = value;
+                    result = COAP_204_CHANGED;
+                }
+                else
+                {
+                    result = COAP_406_NOT_ACCEPTABLE;
+                }
+            }
+            else
+            {
+                result = COAP_400_BAD_REQUEST;
+            }
+            break;
+        }
+        default:
+            return COAP_404_NOT_FOUND;
+        }
+        i++;
+    } while (i < numData && result == COAP_204_CHANGED);
+
+    return result;
+}
+
+static uint8_t prv_security_delete(uint16_t id,
+                                   lwm2m_object_t * objectP)
+{
+    security_instance_t * targetP;
+
+    objectP->instanceList = lwm2m_list_remove(objectP->instanceList, id, (lwm2m_list_t **)&targetP);
+    if (NULL == targetP) return COAP_404_NOT_FOUND;
+    if (NULL != targetP->uri)
+    {
+        lwm2m_free(targetP->uri);
+    }
+
+    lwm2m_free(targetP);
+
+    return COAP_202_DELETED;
+}
+
+static uint8_t prv_security_create(uint16_t instanceId,
+                                   int numData,
+                                   lwm2m_data_t * dataArray,
+                                   lwm2m_object_t * objectP)
+{
+    security_instance_t * targetP;
+    uint8_t result;
+
+    targetP = (security_instance_t *)lwm2m_malloc(sizeof(security_instance_t));
+    if (NULL == targetP) return COAP_500_INTERNAL_SERVER_ERROR;
+    memset(targetP, 0, sizeof(security_instance_t));
+
+    targetP->instanceId = instanceId;
+    objectP->instanceList = LWM2M_LIST_ADD(objectP->instanceList, targetP);
+
+    result = prv_security_write(instanceId, numData, dataArray, objectP);
+
+    if (result != COAP_204_CHANGED)
+    {
+        (void)prv_security_delete(instanceId, objectP);
+    }
+    else
+    {
+        result = COAP_201_CREATED;
+    }
+
+    return result;
+}
+#endif
+
+void copy_security_object(lwm2m_object_t * objectDest, lwm2m_object_t * objectSrc)
+{
+    memcpy(objectDest, objectSrc, sizeof(lwm2m_object_t));
+    objectDest->instanceList = NULL;
+    objectDest->userData = NULL;
+    security_instance_t * instanceSrc = (security_instance_t *)objectSrc->instanceList;
+    security_instance_t * previousInstanceDest = NULL;
+    while (instanceSrc != NULL)
+    {
+        security_instance_t * instanceDest = (security_instance_t *)lwm2m_malloc(sizeof(security_instance_t));
+        if (NULL == instanceDest)
+        {
+            return;
+        }
+        memcpy(instanceDest, instanceSrc, sizeof(security_instance_t));
+        instanceDest->uri = (char*)lwm2m_malloc(strlen(instanceSrc->uri) + 1);
+        strcpy(instanceDest->uri, instanceSrc->uri);
+        if (instanceSrc->securityMode == LWM2M_SECURITY_MODE_PRE_SHARED_KEY)
+        {
+            instanceDest->publicIdentity = lwm2m_strdup(instanceSrc->publicIdentity);
+            instanceDest->secretKey = lwm2m_strdup(instanceSrc->secretKey);
+        }
+        instanceSrc = (security_instance_t *)instanceSrc->next;
+        if (previousInstanceDest == NULL)
+        {
+            objectDest->instanceList = (lwm2m_list_t *)instanceDest;
+        }
+        else
+        {
+            previousInstanceDest->next = instanceDest;
+        }
+        previousInstanceDest = instanceDest;
+    }
+}
+
+void display_security_object(lwm2m_object_t * object)
+{
+#ifdef WITH_LOGS
+    fprintf(stdout, "  /%u: Security object, instances:\r\n", object->objID);
+    security_instance_t * instance = (security_instance_t *)object->instanceList;
+    while (instance != NULL)
+    {
+        fprintf(stdout, "    /%u/%u: instanceId: %u, uri: %s, isBootstrap: %s, shortId: %u, clientHoldOffTime: %u\r\n",
+                object->objID, instance->instanceId,
+                instance->instanceId, instance->uri, instance->isBootstrap ? "true" : "false",
+                instance->shortID, instance->clientHoldOffTime);
+        instance = (security_instance_t *)instance->next;
+    }
+#endif
+}
+
+void clean_security_object(lwm2m_object_t * objectP)
+{
+    while (objectP->instanceList != NULL)
+    {
+        security_instance_t * securityInstance = (security_instance_t *)objectP->instanceList;
+        objectP->instanceList = objectP->instanceList->next;
+        if (NULL != securityInstance->uri)
+        {
+            lwm2m_free(securityInstance->uri);
+        }
+        if (securityInstance->securityMode == LWM2M_SECURITY_MODE_PRE_SHARED_KEY)
+        {
+            lwm2m_free(securityInstance->publicIdentity);
+            lwm2m_free(securityInstance->secretKey);
+        }
+        lwm2m_free(securityInstance);
+    }
+}
+
+lwm2m_object_t * get_security_object(int serverId,
+                                     const char* serverUri,
+                                     char * bsPskId,
+                                     char * psk,
+                                     uint16_t pskLen,
+                                     bool isBootstrap)
 {
     lwm2m_object_t * securityObj;
 
@@ -211,34 +524,51 @@
 
         memset(targetP, 0, sizeof(security_instance_t));
         targetP->instanceId = 0;
-        targetP->uri = strdup("coap://localhost:5683");
-        targetP->isBootstrap = false;
-        targetP->shortID = 123;
+        targetP->uri = (char*)lwm2m_malloc(strlen(serverUri)+1); 
+        strcpy(targetP->uri, serverUri);
+
+        targetP->securityMode = LWM2M_SECURITY_MODE_NONE;
+        targetP->publicIdentity = NULL;
+        targetP->publicIdLen = 0;
+        targetP->secretKey = NULL;
+        targetP->secretKeyLen = 0;
+        if (bsPskId != NULL || psk != NULL)
+        {
+            targetP->securityMode = LWM2M_SECURITY_MODE_PRE_SHARED_KEY;
+            if (bsPskId)
+            {
+                targetP->publicIdentity = strdup(bsPskId);
+                targetP->publicIdLen = strlen(bsPskId);
+            }
+            if (pskLen > 0)
+            {
+                targetP->secretKey = (char*)lwm2m_malloc(pskLen);
+                if (targetP->secretKey == NULL)
+                {
+                    clean_security_object(securityObj);
+                    return NULL;
+                }
+                memcpy(targetP->secretKey, psk, pskLen);
+                targetP->secretKeyLen = pskLen;
+            }
+        }
+        targetP->isBootstrap = isBootstrap;
+        targetP->shortID = serverId;
         targetP->clientHoldOffTime = 10;
 
         securityObj->instanceList = LWM2M_LIST_ADD(securityObj->instanceList, targetP);
 
         securityObj->readFunc = prv_security_read;
+#ifdef LWM2M_BOOTSTRAP
+        securityObj->writeFunc = prv_security_write;
+        securityObj->createFunc = prv_security_create;
+        securityObj->deleteFunc = prv_security_delete;
+#endif
     }
 
     return securityObj;
 }
 
-void free_security_object(lwm2m_object_t * objectP)
-{
-    while (objectP->instanceList != NULL)
-    {
-        security_instance_t * securityInstance = (security_instance_t *)objectP->instanceList;
-        objectP->instanceList = objectP->instanceList->next;
-        if (NULL != securityInstance->uri)
-        {
-            lwm2m_free(securityInstance->uri);
-        }
-        lwm2m_free(securityInstance);
-    }
-    lwm2m_free(objectP);
-}
-
 char * get_server_uri(lwm2m_object_t * objectP,
                       uint16_t secObjInstID)
 {