#define CA_OPTION_URI_QUERY 15
#define CA_OPTION_ACCEPT 17
#define CA_OPTION_LOCATION_QUERY 20
+
+/**
+ * @def UUID_PREFIX
+ * @brief uuid prefix in certificate subject field
+ */
+#define UUID_PREFIX "uuid:"
+
+/**
+ * @def SUBJECT_PREFIX
+ * @brief prefix for specifying part of a cert's subject for a particular uuid
+ */
+#define SUBJECT_PREFIX "CN=" UUID_PREFIX
/**
* TODO: Move these COAP defines to CoAP lib once approved.
#endif
} CAEndpoint_t;
+#define CA_SECURE_ENDPOINT_PUBLIC_KEY_MAX_LENGTH (128)
+
/**
* Endpoint information for secure messages.
*/
CARemoteId_t identity; /**< endpoint device uuid */
CARemoteId_t userId; /**< endpoint user uuid */
uint32_t attributes;
+ uint8_t publicKey[CA_SECURE_ENDPOINT_PUBLIC_KEY_MAX_LENGTH]; /**< Peer's DER-encoded public key (if using certificate) */
+ size_t publicKeyLength; /**< Length of publicKey; zero if not using certificate */
} CASecureEndpoint_t;
/**
if target_os in ['windows', 'msys_nt']:
libocsrm_env.AppendUnique(LIBPATH = [os.path.join(libocsrm_env.get('BUILD_DIR'), 'resource', 'oc_logger')])
- # Enable W4 but disable the following warning:
- # - warning C4232: nonstandard extension used: 'read': address of dllimport 'fread' is not static, identity not guaranteed
- # - fread, frwrite, etc are provided by the platform and cannot be changed.
- libocsrm_env.AppendUnique(CCFLAGS=['/W4', '/WX'])
+ # - warning C4200: nonstandard extension used: zero-sized array in struct/union
+ # - warning C4214: nonstandard extension used: bit field types other than int
+ # - warnings inherited from a header included from libcoap
- libocsrm_env.AppendUnique(CCFLAGS=['/wd4232', '/wd4200', '/wd4214', '/W4', '/WX'])
++ libocsrm_env.AppendUnique(CCFLAGS=['/wd4200', '/wd4214', '/W4', '/WX'])
if target_os in ['linux', 'android', 'tizen', 'msys_nt', 'windows'] and libocsrm_env.get('SECURED') == '1':
SConscript('provisioning/SConscript', 'libocsrm_env')
libocsrm_src = libocsrm_src + [OCSRM_SRC + 'oxmpincommon.c', OCSRM_SRC + 'pbkdf2.c']
libocsrm_src = libocsrm_src + [OCSRM_SRC + 'crlresource.c', OCSRM_SRC + 'pkix_interface.c']
libocsrm_src = libocsrm_src + [OCSRM_SRC + 'oxmverifycommon.c']
+ libocsrm_src = libocsrm_src + [OCSRM_SRC + 'certhelpers.c', OCSRM_SRC + 'occertutility.c']
+ libocsrm_src = libocsrm_src + [OCSRM_SRC + 'csrresource.c']
+ libocsrm_src = libocsrm_src + [OCSRM_SRC + 'rolesresource.c']
if target_os in ['windows', 'msys_nt']:
libocsrm_src = libocsrm_src + [OCSRM_SRC + 'strptime.c']
* will have to be written by hand to marshal these structures (e.g. to/from
* Persistent Storage, or across memory boundaries).
*
+ * We're using uint typedefs for all enum types to avoid C++ type conversion
+ * errors and enable bitfield operations on these fields (causes compilation
+ * errors on arduino builds). This may miss some type checks, but it's
+ * nearly impossible to do int/bitfield operations on enum types in C++.
+ *
* TODO reconcile against latest OIC Security Spec to ensure all fields correct.
* (Last checked against v0.95)
*/
* }
* }
*/
- typedef enum
+ enum
{
ACCESS_GRANTED = ACCESS_GRANTED_DEF,
ACCESS_DENIED = ACCESS_DENIED_DEF,
| POLICY_ENGINE_ERROR_DEF,
ACCESS_DENIED_SEC_RESOURCE_OVER_UNSECURE_CHANNEL = ACCESS_DENIED_DEF
| SEC_RESOURCE_OVER_UNSECURE_CHANNEL_DEF,
- } SRMAccessResponse_t;
+ };
+
+ typedef unsigned int SRMAccessResponse_t;
/**
* Reason code for SRMAccessResponse.
*/
- typedef enum
+ enum
{
NO_REASON_GIVEN = 0,
INSUFFICIENT_PERMISSION = INSUFFICIENT_PERMISSION_DEF,
SUBJECT_NOT_FOUND = SUBJECT_NOT_FOUND_DEF,
RESOURCE_NOT_FOUND = RESOURCE_NOT_FOUND_DEF,
- } SRMAccessResponseReasonCode_t;
+ };
+
+ typedef unsigned int SRMAccessResponseReasonCode_t;
/**
* Extract Reason Code from Access Response.
* // ct contains PIN_PASSWORD flag.
* }
*/
- typedef enum OSCTBitmask
+ enum OSCTBitmask
{
NO_SECURITY_MODE = 0x0,
SYMMETRIC_PAIR_WISE_KEY = (0x1 << 0),
SIGNED_ASYMMETRIC_KEY = (0x1 << 3),
PIN_PASSWORD = (0x1 << 4),
ASYMMETRIC_ENCRYPTION_KEY = (0x1 << 5),
- } OSCTBitmask_t;
+ };
+
+ typedef unsigned int OSCTBitmask_t;
/**
* /oic/sec/credtype (Credential Type) data type.
typedef struct OicSecDoxm OicSecDoxm_t;
- typedef enum OicSecDpm
+ /**
+ * The oic.sec.dpmtype
+ */
+ enum OicSecDpm
{
NORMAL = 0x0,
RESET = (0x1 << 0),
SECURITY_MANAGEMENT_SERVICES = (0x1 << 3),
PROVISION_CREDENTIALS = (0x1 << 4),
PROVISION_ACLS = (0x1 << 5),
+ VERIFY_SOFTWARE_VERSION = (0x1 << 6),
+ UPDATE_SOFTWARE = (0x1 << 7),
#ifdef MULTIPLE_OWNER
- TAKE_SUB_OWNER = (0x1 << 6),
+ TAKE_SUB_OWNER = (0x1 << 13),
#endif
- // << 7 THROUGH 15 RESERVED
- } OicSecDpm_t;
+ };
+
+ typedef unsigned int OicSecDpm_t;
// These types are taken from the Security Spec v1.1.12 /pstat resource definition
// Note that per the latest spec, there is NO definition for Multiple Service Client Directed
// provisioning mode, so that enum value has been removed.
- typedef enum OicSecDpom
+ enum OicSecDpom
{
MULTIPLE_SERVICE_SERVER_DRIVEN = (0x1 << 0),
SINGLE_SERVICE_SERVER_DRIVEN = (0x1 << 1),
SINGLE_SERVICE_CLIENT_DRIVEN = (0x1 << 2),
- } OicSecDpom_t;
+ };
- typedef enum OicSecSvcType
+ typedef unsigned int OicSecDpom_t;
+
+ enum OicSecSvcType
{
SERVICE_UNKNOWN = 0x0,
ACCESS_MGMT_SERVICE = 0x1, //urn:oic.sec.ams
- } OicSecSvcType_t;
+ };
+ typedef unsigned int OicSecSvcType_t;
//TODO: Need more clarification on deviceIDFormat field type.
#if 0
- typedef enum
+ enum
{
URN = 0x0
- }OicSecDvcIdFrmt_t;
+ };
+
+ typedef unsigned int OicSecDvcIdFrmt_t;
#endif
- typedef enum
+ enum
{
OIC_RESOURCE_TYPE_ERROR = 0,
OIC_R_ACL_TYPE,
OIC_R_AMACL_TYPE,
OIC_R_CRED_TYPE,
OIC_R_CRL_TYPE,
+ OIC_R_CSR_TYPE,
OIC_R_DOXM_TYPE,
OIC_R_DPAIRING_TYPE,
OIC_R_PCONF_TYPE,
OIC_R_PSTAT_TYPE,
+ OIC_R_ROLES_TYPE,
OIC_R_SACL_TYPE,
OIC_R_SVC_TYPE,
OIC_SEC_SVR_TYPE_COUNT, //define the value to number of SVR
NOT_A_SVR_RESOURCE = 99
- }OicSecSvrType_t;
+ };
- typedef enum
+ typedef unsigned int OicSecSvrType_t;
+
+ enum
{
OIC_JUST_WORKS = 0x0,
OIC_RANDOM_DEVICE_PIN = 0x1,
#endif //MULTIPLE_OWNER
OIC_MV_JUST_WORKS = 0xFF01,
OIC_CON_MFG_CERT = 0xFF02,
- }OicSecOxm_t;
+ };
- typedef enum
+ typedef unsigned int OicSecOxm_t;
+
+ enum
{
OIC_ENCODING_UNKNOW = 0,
OIC_ENCODING_RAW = 1,
OIC_ENCODING_BASE64 = 2,
OIC_ENCODING_PEM = 3,
OIC_ENCODING_DER = 4
- }OicEncodingType_t;
+ };
+
+ typedef unsigned int OicEncodingType_t;
#ifdef MULTIPLE_OWNER
- typedef enum
+ enum
{
MOT_STATUS_READY = 0,
MOT_STATUS_IN_PROGRESS = 1,
MOT_STATUS_DONE = 2,
- }MotStatus_t;
+ };
+
+ typedef unsigned int MotStatus_t;
#endif //MULTIPLE_OWNER
/**
* 1 : Enable multiple owner (Always on)
* 2 : Timely multiple owner enable
*/
- typedef enum
+ enum
{
OIC_MULTIPLE_OWNER_DISABLE = 0,
OIC_MULTIPLE_OWNER_ENABLE = 1,
OIC_MULTIPLE_OWNER_TIMELY_ENABLE = 2,
OIC_NUMBER_OF_MOM_TYPE = 3
- }OicSecMomType_t;
+ };
+
+ typedef unsigned int OicSecMomType_t;
typedef struct OicSecKey OicSecKey_t;
*/
#define UUID_LENGTH 128/8 // 128-bit GUID length
//TODO: Confirm the length and type of ROLEID.
-#define ROLEID_LENGTH 128/8 // 128-bit ROLEID length
+#define ROLEID_LENGTH 64 // 64-byte authority max length
+#define ROLEAUTHORITY_LENGTH 64 // 64-byte authority max length
#define OWNER_PSK_LENGTH_128 128/8 //byte size of 128-bit key size
#define OWNER_PSK_LENGTH_256 256/8 //byte size of 256-bit key size
OicSecValidity_t *next;
};
+typedef enum
+{
+ OIC_SEC_ACL_UNKNOWN = 0,
+ OIC_SEC_ACL_V1 = 1,
+ OIC_SEC_ACL_V2 = 2
+} OicSecAclVersion_t;
+
+#define OIC_SEC_ACL_LATEST OIC_SEC_ACL_V2
+
+typedef enum
+{
+ OicSecAceUuidSubject = 0, /* Default to this type. */
+ OicSecAceRoleSubject
+} OicSecAceSubjectType;
+
+/**
+ * /oic/sec/role (Role) data type.
+ * Derived from OIC Security Spec; see Spec for details.
+ */
+struct OicSecRole
+{
+ // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+ char id[ROLEID_LENGTH]; // 0:R:S:Y:String
+ char authority[ROLEAUTHORITY_LENGTH]; // 1:R:S:N:String
+};
+
struct OicSecAce
{
// <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
- OicUuid_t subjectuuid; // 0:R:S:Y:uuid
+ OicSecAceSubjectType subjectType;
+ union // 0:R:S:Y:{roletype|didtype|"*"}
+ {
+ OicUuid_t subjectuuid; // Only valid for subjectType == OicSecAceUuidSubject
+ OicSecRole_t subjectRole; // Only valid for subjectType == OicSecAceRoleSubject
+ };
OicSecRsrc_t *resources; // 1:R:M:Y:Resource
uint16_t permission; // 2:R:S:Y:UINT16
OicSecValidity_t *validities; // 3:R:M:N:Time-interval
{
// <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
bool isOp; // 0:R:S:Y:Boolean
- OicSecDpm_t cm; // 1:R:S:Y:oic.sec.dpm
- OicSecDpm_t tm; // 2:RW:S:Y:oic.sec.dpm
+ OicSecDpm_t cm; // 1:R:S:Y:oic.sec.dpmtype
+ OicSecDpm_t tm; // 2:RW:S:Y:oic.sec.dpmtype
OicSecDpom_t om; // 4:RW:M:Y:oic.sec.dpom
size_t smLen; // the number of elts in Sm
OicSecDpom_t *sm; // 5:R:M:Y:oic.sec.dpom
};
/**
- * /oic/sec/role (Role) data type.
- * Derived from OIC Security Spec; see Spec for details.
- */
-struct OicSecRole
-{
- // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
- //TODO fill in with Role definition
- uint8_t id[ROLEID_LENGTH];
-};
-
-/**
* /oic/sec/sacl (Signed Access Control List) data type.
* Derived from OIC Security Spec; see Spec for details.
*/
* 1: pre-configured pin
* 2: random pin
*/
- typedef enum PRMBitmask
+ enum PRMBitmask
{
PRM_NOT_ALLOWED = 0x0,
PRM_PRE_CONFIGURED = (0x1 << 0),
PRM_RANDOM_PIN = (0x1 << 1),
- } PRMBitmask_t;
+ };
- typedef PRMBitmask_t OicSecPrm_t;
+ typedef unsigned int OicSecPrm_t;
struct OicPin
#include "secureresourcemanager.h"
#include "srmresourcestrings.h"
#include "ocresourcehandler.h"
+ #include "ocrandom.h"
#if defined( __WITH_TLS__) || defined(__WITH_DTLS__)
#include "pkix_interface.h"
// on to resource endpoint.
if (IsAccessGranted(context->responseVal))
{
- if(NULL != gRequestHandler
+ if (NULL != gRequestHandler
&& NULL != context->endPoint
&& NULL != context->requestInfo)
{
context->resourceType, context->resourceUri);
// if request is over unsecure channel, check resource type
- if(false == context->secureChannel)
+ if (false == context->secureChannel)
{
OCResource *resPtr = FindResourceByUri(context->resourceUri);
}
// Returns true iff Request arrived over secure channel
+ // Note: context->subjectUuid must be copied from requestInfo prior to calling
+ // this function, or this function may incorrectly read the nil-UUID (0s)
+ // and assume CoAP request (which can result in request being incorrectly
+ // denied).
bool isRequestOverSecureChannel(SRMRequestContext_t *context)
{
OicUuid_t nullSubjectId = {.id = {0}};
- // if flag set, return true
- if(context->endPoint->flags & CA_SECURE)
+ // If flag set, return true
+ if (context->endPoint->flags & CA_SECURE)
{
+ OIC_LOG(DEBUG, TAG, "CA_SECURE flag is set; indicates secure channel.");
return true;
}
- // a null subject ID indicates CoAP, so if non-null, also return true
- else if(memcmp(context->requestInfo->info.identity.id,
- nullSubjectId.id, sizeof(context->requestInfo->info.identity.id)) != 0)
+
+ // A null subject ID indicates CoAP, so if non-null, also return true
+ if (SUBJECT_ID_TYPE_UUID == context->subjectIdType)
{
- return true;
+ if (memcmp(context->subjectUuid.id, nullSubjectId.id,
+ sizeof(context->subjectUuid.id)) != 0)
+ {
+ OIC_LOG(DEBUG, TAG, "Subject ID is non-null; indicates secure channel.");
+ return true;
+ }
}
+ OIC_LOG(DEBUG, TAG, "CA_SECURE flag is not set, and Subject ID of requester \
+ is NULL; indicates unsecure channel.");
return false;
}
ctx->requestInfo = requestInfo;
ctx->requestedPermission = GetPermissionFromCAMethod_t(requestInfo->method);
- // Copy the subjectID.
+ // Copy the subjectID, truncating to 16-byte UUID (32 hex-digits).
+ // TODO IOT-1894 "Determine appropriate CA_MAX_ENDPOINT_IDENTITY_LEN"
+ ctx->subjectIdType = SUBJECT_ID_TYPE_UUID; // only supported type for now
memcpy(ctx->subjectUuid.id,
requestInfo->info.identity.id, sizeof(ctx->subjectUuid.id));
- ctx->subjectIdType = SUBJECT_ID_TYPE_UUID; // only supported type for now
+
+ #ifndef NDEBUG // if debug build, log the ID being used for matching ACEs
+ if (SUBJECT_ID_TYPE_UUID == ctx->subjectIdType)
+ {
+ char strUuid[UUID_STRING_SIZE] = "UUID_ERROR";
+ if (OCConvertUuidToString(ctx->subjectUuid.id, strUuid))
+ {
+ OIC_LOG_V(DEBUG, TAG, "ctx->subjectUuid for request: %s.", strUuid);
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "failed to convert ctx->subjectUuid to str.");
+ }
+ }
+ #endif
// Set secure channel boolean.
ctx->secureChannel = isRequestOverSecureChannel(ctx);
CheckRequestForSecResourceOverUnsecureChannel(ctx);
// If DENIED response wasn't sent already, then it's time to check ACL.
- if(false == ctx->responseSent)
+ if (false == ctx->responseSent)
{
#ifdef MULTIPLE_OWNER // TODO Samsung: please verify that these two calls belong
// here inside this conditional statement.
}
}
- if(false == ctx->responseSent)
+ if (false == ctx->responseSent)
{
OIC_LOG(ERROR, TAG, "Exiting SRM without responding to requester!");
}
CAResponseCallback respHandler, CAErrorCallback errHandler)
{
OIC_LOG(DEBUG, TAG, "SRMRegisterHandler !!");
- if( !reqHandler || !respHandler || !errHandler)
+ if (!reqHandler || !respHandler || !errHandler)
{
OIC_LOG(ERROR, TAG, "Callback handlers are invalid");
return OC_STACK_INVALID_PARAM;
OIC_RSRC_AMACL_URI,
OIC_RSRC_CRL_URI,
OIC_RSRC_CRED_URI,
+ OIC_RSRC_CSR_URI,
OIC_RSRC_ACL_URI,
OIC_RSRC_DOXM_URI,
OIC_RSRC_PSTAT_URI,
OIC_RSRC_PCONF_URI,
OIC_RSRC_DPAIRING_URI,
OIC_RSRC_VER_URI,
+ OIC_RSRC_ROLES_URI,
OC_RSRVD_PROV_CRL_URL
};
size_t svrLen = 0;
svrLen = strlen(OIC_RSRC_ACL_URI);
- if(uriLen == svrLen)
+ if (uriLen == svrLen)
{
- if(0 == strncmp(uri, OIC_RSRC_ACL_URI, svrLen))
+ if (0 == strncmp(uri, OIC_RSRC_ACL_URI, svrLen))
{
return OIC_R_ACL_TYPE;
}
}
svrLen = strlen(OIC_RSRC_AMACL_URI);
- if(uriLen == svrLen)
+ if (uriLen == svrLen)
{
- if(0 == strncmp(uri, OIC_RSRC_AMACL_URI, svrLen))
+ if (0 == strncmp(uri, OIC_RSRC_AMACL_URI, svrLen))
{
return OIC_R_AMACL_TYPE;
}
}
svrLen = strlen(OIC_RSRC_CRED_URI);
- if(uriLen == svrLen)
+ if (uriLen == svrLen)
{
- if(0 == strncmp(uri, OIC_RSRC_CRED_URI, svrLen))
+ if (0 == strncmp(uri, OIC_RSRC_CRED_URI, svrLen))
{
return OIC_R_CRED_TYPE;
}
}
svrLen = strlen(OIC_RSRC_CRL_URI);
- if(uriLen == svrLen)
+ if (uriLen == svrLen)
{
- if(0 == strncmp(uri, OIC_RSRC_CRL_URI, svrLen))
+ if (0 == strncmp(uri, OIC_RSRC_CRL_URI, svrLen))
{
return OIC_R_CRL_TYPE;
}
}
+ svrLen = strlen(OIC_RSRC_CSR_URI);
+ if (uriLen == svrLen)
+ {
+ if (0 == strncmp(uri, OIC_RSRC_CSR_URI, svrLen))
+ {
+ return OIC_R_CSR_TYPE;
+ }
+ }
+
svrLen = strlen(OIC_RSRC_DOXM_URI);
- if(uriLen == svrLen)
+ if (uriLen == svrLen)
{
- if(0 == strncmp(uri, OIC_RSRC_DOXM_URI, svrLen))
+ if (0 == strncmp(uri, OIC_RSRC_DOXM_URI, svrLen))
{
return OIC_R_DOXM_TYPE;
}
}
svrLen = strlen(OIC_RSRC_DPAIRING_URI);
- if(uriLen == svrLen)
+ if (uriLen == svrLen)
{
- if(0 == strncmp(uri, OIC_RSRC_DPAIRING_URI, svrLen))
+ if (0 == strncmp(uri, OIC_RSRC_DPAIRING_URI, svrLen))
{
return OIC_R_DPAIRING_TYPE;
}
}
svrLen = strlen(OIC_RSRC_PCONF_URI);
- if(uriLen == svrLen)
+ if (uriLen == svrLen)
{
- if(0 == strncmp(uri, OIC_RSRC_PCONF_URI, svrLen))
+ if (0 == strncmp(uri, OIC_RSRC_PCONF_URI, svrLen))
{
return OIC_R_PCONF_TYPE;
}
}
svrLen = strlen(OIC_RSRC_PSTAT_URI);
- if(uriLen == svrLen)
+ if (uriLen == svrLen)
{
- if(0 == strncmp(uri, OIC_RSRC_PSTAT_URI, svrLen))
+ if (0 == strncmp(uri, OIC_RSRC_PSTAT_URI, svrLen))
{
return OIC_R_PSTAT_TYPE;
}
}
+ svrLen = strlen(OIC_RSRC_ROLES_URI);
+ if (uriLen == svrLen)
+ {
+ if (0 == strncmp(uri, OIC_RSRC_ROLES_URI, svrLen))
+ {
+ return OIC_R_ROLES_TYPE;
+ }
+ }
+
svrLen = strlen(OIC_RSRC_SVC_URI);
- if(uriLen == svrLen)
+ if (uriLen == svrLen)
{
- if(0 == strncmp(uri, OIC_RSRC_SVC_URI, svrLen))
+ if (0 == strncmp(uri, OIC_RSRC_SVC_URI, svrLen))
{
return OIC_R_SVC_TYPE;
}
}
svrLen = strlen(OIC_RSRC_SACL_URI);
- if(uriLen == svrLen)
+ if (uriLen == svrLen)
{
- if(0 == strncmp(uri, OIC_RSRC_SACL_URI, svrLen))
+ if (0 == strncmp(uri, OIC_RSRC_SACL_URI, svrLen))
{
return OIC_R_SACL_TYPE;
}