Skip to content

Commit

Permalink
MFi token auth support
Browse files Browse the repository at this point in the history
  • Loading branch information
rojer committed Sep 13, 2021
1 parent bd85f86 commit cd705ab
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 175 deletions.
3 changes: 3 additions & 0 deletions mos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ conds:
- ["hap", "o", {"title": "HAP settings"}]
- ["hap.salt", "s", "", {"title": "Device verifier salt"}]
- ["hap.verifier", "s", "", {"title": "Device verifier"}]
- ["hap.setup_id", "s", "", {"title": "Setup ID"}]
- ["hap.mfi_uuid", "s", "", {"title": "MFi UUID, in RFC 4122 representation (8-4-4-4-12)"}]
- ["hap.mfi_token", "s", "", {"title": "MFi token, Base64"}]
cdefs:
MGOS_HAP_SIMPLE_CONFIG: 1
MGOS_HAP_SIMPLE_CONFIG_LEVEL: 2 # Config level to use for HAP info.
Expand Down
45 changes: 3 additions & 42 deletions src/PAL/HAPPlatformMFiTokenAuth+Init.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
// you may not use this file except in compliance with the License.
// See [CONTRIBUTORS.md] for the list of HomeKit ADK project authors.

#ifndef HAP_PLATFORM_MFI_TOKEN_AUTH_INIT_H
#define HAP_PLATFORM_MFI_TOKEN_AUTH_INIT_H
#pragma once

#ifdef __cplusplus
extern "C" {
Expand All @@ -17,49 +16,13 @@ extern "C" {
#pragma clang assume_nonnull begin
#endif

/**@file
* Software Token provider.
*
* The linked key-value store needs to be provisioned with software token information
* before this implementation may be used. Please refer to the Provision tool.
*
* **Example**
@code{.c}
// Get dependencies.
HAPPlatformKeyValueStoreRef keyValueStore;
// Allocate Software Token provider.
static HAPPlatformMFiTokenAuth mfiTokenAuth;
// Initialize Software Token provider.
HAPPlatformMFiTokenAuthCreate(&mfiTokenAuth,
&(const HAPPlatformMFiTokenAuthOptions) {
.keyValueStore = keyValueStore
});
@endcode
*/

/**
* Software token provider initialization options.
*/
typedef struct {
/**
* Key-value store.
*/
HAPPlatformKeyValueStoreRef keyValueStore;
uint8_t dummy;
} HAPPlatformMFiTokenAuthOptions;

/**
* Software Token provider.
*/
struct HAPPlatformMFiTokenAuth {
// Opaque type. Do not access the instance fields directly.
/**@cond */
uint8_t dummy;
HAPPlatformKeyValueStoreRef keyValueStore;
/**@endcond */
};

/**
Expand Down Expand Up @@ -89,5 +52,3 @@ bool HAPPlatformMFiTokenAuthIsProvisioned(HAPPlatformMFiTokenAuthRef mfiTokenAut
#ifdef __cplusplus
}
#endif

#endif
166 changes: 74 additions & 92 deletions src/PAL/HAPPlatformMFiTokenAuth.c
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
// Copyright (c) 2015-2019 The HomeKit ADK Contributors
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
// See [CONTRIBUTORS.md] for the list of HomeKit ADK project authors.

// Note: This uese KV store but should use mos config.
/*
* Copyright (c) 2021 Deomid "rojer" Ryabkov
* All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <stdio.h>

#include "HAPPlatform.h"
#include "HAPPlatformKeyValueStore+SDKDomains.h"
#include "HAPPlatformMFiTokenAuth+Init.h"

static const HAPLogObject logObject = { .subsystem = kHAPPlatform_LogSubsystem, .category = "MFiTokenAuth" };
#include "mgos.h"

void HAPPlatformMFiTokenAuthCreate(
HAPPlatformMFiTokenAuthRef mfiTokenAuth,
const HAPPlatformMFiTokenAuthOptions* options) {
HAPPrecondition(mfiTokenAuth);
HAPPrecondition(options);
HAPPrecondition(options->keyValueStore);

mfiTokenAuth->keyValueStore = options->keyValueStore;
mfiTokenAuth->keyValueStore = NULL;
(void) options;
}

HAP_RESULT_USE_CHECK
Expand All @@ -36,67 +44,61 @@ HAPError HAPPlatformMFiTokenAuthLoad(
HAPPrecondition(!maxMFiTokenBytes || mfiTokenBytes);
HAPPrecondition((mfiTokenBytes == NULL) == (numMFiTokenBytes == NULL));

HAPError err;

bool foundMFiTokenUUID;
size_t numMFiTokenUUIDBytes = 0;
err = HAPPlatformKeyValueStoreGet(
mfiTokenAuth->keyValueStore,
kSDKKeyValueStoreDomain_Provisioning,
kSDKKeyValueStoreKey_Provisioning_MFiTokenUUID,
mfiTokenUUID,
mfiTokenUUID ? sizeof *mfiTokenUUID : 0,
mfiTokenUUID ? &numMFiTokenUUIDBytes : NULL,
&foundMFiTokenUUID);
if (err) {
HAPAssert(err == kHAPError_Unknown);
return err;
}
bool foundMFiToken;
size_t numMFiTokenBytes_ = 0;
err = HAPPlatformKeyValueStoreGet(
mfiTokenAuth->keyValueStore,
kSDKKeyValueStoreDomain_Provisioning,
kSDKKeyValueStoreKey_Provisioning_MFiToken,
mfiTokenBytes,
maxMFiTokenBytes,
mfiTokenBytes ? &numMFiTokenBytes_ : NULL,
&foundMFiToken);
if (err) {
HAPAssert(err == kHAPError_Unknown);
return err;
*valid = false;

const char* uuid_str = mgos_sys_config_get_hap_mfi_uuid();
const char* token_str = mgos_sys_config_get_hap_mfi_token();
if (mgos_conf_str_empty(uuid_str) || mgos_conf_str_empty(token_str)) {
return kHAPError_None;
}
if (numMFiTokenBytes) {
*numMFiTokenBytes = numMFiTokenBytes_;

size_t uuid_str_len = strlen(uuid_str);
size_t token_str_len = strlen(token_str);
if (uuid_str_len != 36 || token_str_len > 1368) {
return kHAPError_Unknown;
}

*valid = foundMFiTokenUUID && foundMFiToken;
if (!*valid) {
return kHAPError_None;
if (mfiTokenUUID != NULL) {
unsigned int uuid_bytes[32];
if (sscanf(uuid_str,
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
&uuid_bytes[15],
&uuid_bytes[14],
&uuid_bytes[13],
&uuid_bytes[12],
&uuid_bytes[11],
&uuid_bytes[10],
&uuid_bytes[9],
&uuid_bytes[8],
&uuid_bytes[7],
&uuid_bytes[6],
&uuid_bytes[5],
&uuid_bytes[4],
&uuid_bytes[3],
&uuid_bytes[2],
&uuid_bytes[1],
&uuid_bytes[0]) != 16) {
return kHAPError_Unknown;
}
for (int i = 0; i < 16; i++) {
mfiTokenUUID->bytes[i] = (uint8_t) uuid_bytes[i];
}
}
if (numMFiTokenBytes && *numMFiTokenBytes == maxMFiTokenBytes) {
HAPLog(&logObject,
"Software Token does not fit into buffer: available = %lu bytes.",
(unsigned long) maxMFiTokenBytes);
return kHAPError_OutOfResources;

if (mfiTokenBytes != NULL && maxMFiTokenBytes > 0) {
int dlen = 0;
cs_base64_decode((const void*) token_str, (int) token_str_len, mfiTokenBytes, &dlen);
*numMFiTokenBytes = dlen;
}

*valid = true;

return kHAPError_None;
}

bool HAPPlatformMFiTokenAuthIsProvisioned(HAPPlatformMFiTokenAuthRef mfiTokenAuth) {
HAPPrecondition(mfiTokenAuth);

HAPError err;

bool valid;
err = HAPPlatformMFiTokenAuthLoad(mfiTokenAuth, &valid, NULL, NULL, 0, NULL);
if (err) {
HAPAssert(err == kHAPError_Unknown);
return false;
}

return valid;
return (HAPPlatformMFiTokenAuthLoad(mfiTokenAuth, &valid, NULL, NULL, 0, NULL) == kHAPError_None && valid);
}

HAP_RESULT_USE_CHECK
Expand All @@ -108,38 +110,18 @@ HAPError HAPPlatformMFiTokenAuthUpdate(
HAPPrecondition(mfiTokenBytes);
HAPPrecondition(numMFiTokenBytes <= kHAPPlatformMFiTokenAuth_MaxMFiTokenBytes);

HAPError err;

// Try to find old Software Token.
bool found;
err = HAPPlatformKeyValueStoreGet(
mfiTokenAuth->keyValueStore,
kSDKKeyValueStoreDomain_Provisioning,
kSDKKeyValueStoreKey_Provisioning_MFiToken,
NULL,
0,
NULL,
&found);
if (err) {
HAPAssert(err == kHAPError_Unknown);
return err;
}
if (!found) {
HAPLogInfo(&logObject, "Trying to update Software Token but no Software Token is present in key-value store.");
char* token_str = calloc((numMFiTokenBytes * 8) / 6 + 10, 1);
if (token_str == NULL) {
return kHAPError_Unknown;
}

// Update Software Token.
err = HAPPlatformKeyValueStoreSet(
mfiTokenAuth->keyValueStore,
kSDKKeyValueStoreDomain_Provisioning,
kSDKKeyValueStoreKey_Provisioning_MFiToken,
mfiTokenBytes,
numMFiTokenBytes);
if (err) {
HAPAssert(err == kHAPError_Unknown);
return err;
}
cs_base64_encode(mfiTokenBytes, numMFiTokenBytes, token_str, NULL);

LOG(LL_INFO, ("Updated token: %s", token_str));

mgos_sys_config_set_hap_mfi_token(token_str);

free(token_str);

return kHAPError_None;
}
11 changes: 7 additions & 4 deletions src/mgos_homekit_adk.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#include "mgos.h"

#include "HAPAccessorySetup.h"

void HAPPlatformAccessorySetupLoadSetupInfo(HAPPlatformAccessorySetupRef accessorySetup, HAPSetupInfo* setupInfo) {
struct mgos_hap_load_setup_info_arg arg = {
.accessorySetup = accessorySetup,
Expand Down Expand Up @@ -123,14 +125,15 @@ static void mgos_hap_load_setup_info_cb(int ev, void* ev_data, void* userdata) {
(void) userdata;
}

HAPSetupID g_hap_setup_id;

static void mgos_hap_load_setup_id_cb(int ev, void* ev_data, void* userdata) {
struct mgos_hap_load_setup_id_arg* arg = (struct mgos_hap_load_setup_id_arg*) ev_data;
if (g_hap_setup_id.stringValue[0] == '\0')
const char* setup_id = mgos_sys_config_get_hap_setup_id();
if (mgos_conf_str_empty(setup_id) || !HAPAccessorySetupIsValidSetupID(setup_id)) {
*arg->valid = false;
return;
}
*arg->valid = true;
*arg->setupID = g_hap_setup_id;
memcpy(arg->setupID->stringValue, setup_id, sizeof(arg->setupID->stringValue));
(void) ev;
(void) userdata;
}
Expand Down
Loading

0 comments on commit cd705ab

Please sign in to comment.