This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

What does this "prov_utils_confirmation_check" function do??

Hi, a little background information first, when debugging ble mesh example 0.9.x:

devzone.nordicsemi.com/.../

I'm now kinda having a massive problem with this function:

bool prov_utils_confirmation_check(const prov_common_ctx_t * p_ctx)
{
uint8_t confirmation_key[NRF_MESH_KEY_SIZE];

/* ConfirmationKey = k1(ECDHSecret, ConfirmationSalt, "prck") */
enc_k1(p_ctx->shared_secret,
       NRF_MESH_ECDH_SHARED_SECRET_SIZE,
       p_ctx->confirmation_salt,
       CONFIRMATION_KEY_INFO, CONFIRMATION_KEY_INFO_LENGTH,
       confirmation_key);

uint8_t random_and_auth[PROV_RANDOM_LEN + PROV_AUTH_LEN];
memcpy(&random_and_auth[0], p_ctx->peer_random, PROV_RANDOM_LEN);
memcpy(&random_and_auth[PROV_RANDOM_LEN], p_ctx->auth_value, PROV_AUTH_LEN);

/* Confirmation value = AES-CMAC(ConfirmationKey, LocalRandom || AuthValue) */
uint8_t confirmation[PROV_CONFIRMATION_LEN];
enc_aes_cmac(confirmation_key,
             random_and_auth,
             PROV_RANDOM_LEN + PROV_AUTH_LEN,
             confirmation);

//int result = memcmp(confirmation, p_ctx->peer_confirmation, sizeof(confirmation)) == 0;
  int result = memcmp(confirmation, p_ctx->peer_confirmation, sizeof(confirmation));
	return result;
}

My question are these:

#Question No.1

The function in question gets called in :

case PROV_PDU_TYPE_RANDOM

But what does this case mean? Why would there be a "RANDOM" payload unit? I completely failed to get the point. For encryption purposes?

#Question No.2

I'm completely lost on these lines:

uint8_t random_and_auth[PROV_RANDOM_LEN + PROV_AUTH_LEN];
memcpy(&random_and_auth[0], p_ctx->peer_random, PROV_RANDOM_LEN);
memcpy(&random_and_auth[PROV_RANDOM_LEN], p_ctx->auth_value, PROV_AUTH_LEN);

And

memcmp(confirmation, p_ctx->peer_confirmation, sizeof(confirmation));

The only possible explanation I can think of is this:

  1. Provisioner send me (provisionee) a random payload (thus "case PROV_PDU_TYPE_RANDOM") which somehow I knew what it is.
  2. In the same payload, provisioner also managed to slip in some confirmation information.
  3. I perform an encryption operation based on the confirmation information provisoner sent me, and come up independently with my own results.
  4. I compare the results with the result I should GET which provisioner sent me and see if the two are completely identical. If they are, then great I can proceed further because no future problem will emerge in our encrypted communications, if not, then I stop because I will not properly decode whatever message provisioner send me.

Is my guess correct? If not, what is it really for?

The result of this function is consistently "-86", can anyone shed some light???

Parents
  • Hi Mitch,

    I would look at the Provisioning documentation or the provisioning protocol in the Mesh Profile specification if you want to understand the provisioning process better.

    In short, the confirmation check is to check that the provisioner/provisionee authenticated correctly against its peer, i.e., that the ECDH key exchange was successful and correctly authenticates against the OOB data. The below figure from Wikipedia explains it pretty well. The secret colours in the figure is the private keys and the common paint the OOB data.

    Key exchange

    Specifically to the issue you're facing, my best guess is that there is an error in handling one of the provisioning events. The Light Control example uses static OOB data. Is this the same for both of your nodes?

    Hope this helps,
    Thomas

  • Have a look at the handling of the NRF_MESH_EVT_PROV_CAPS_RECEIVEDon the provisioner and the NRF_MESH_EVT_PROV_STATIC_REQUEST on both. Is the STATIC_AUTH_DATA identical?

    From examples/light_control/client/src/provisioner.c:

        case NRF_MESH_EVT_PROV_STATIC_REQUEST:
        {
            uint8_t static_data[16] = STATIC_AUTH_DATA;
            ERROR_CHECK(nrf_mesh_prov_auth_data_provide(p_evt->params.prov_static_request.p_context, static_data, 16));
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Static authentication data provided\n");
            break;
        }
    
    • Thomas
Reply
  • Have a look at the handling of the NRF_MESH_EVT_PROV_CAPS_RECEIVEDon the provisioner and the NRF_MESH_EVT_PROV_STATIC_REQUEST on both. Is the STATIC_AUTH_DATA identical?

    From examples/light_control/client/src/provisioner.c:

        case NRF_MESH_EVT_PROV_STATIC_REQUEST:
        {
            uint8_t static_data[16] = STATIC_AUTH_DATA;
            ERROR_CHECK(nrf_mesh_prov_auth_data_provide(p_evt->params.prov_static_request.p_context, static_data, 16));
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Static authentication data provided\n");
            break;
        }
    
    • Thomas
Children
No Data
Related