/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <string.h>
#include "host/ble_hs_id.h"
#include "ble_hs_priv.h"

static uint8_t ble_hs_id_pub[6];
static uint8_t ble_hs_id_rnd[6];
static const uint8_t ble_hs_misc_null_addr[6];


void
ble_hs_id_set_pub(const uint8_t *pub_addr)
{
    ble_hs_lock();
    memcpy(ble_hs_id_pub, pub_addr, 6);
    ble_hs_unlock();
}

int
ble_hs_id_gen_rnd(int nrpa, ble_addr_t *out_addr)
{
    int rc;

    out_addr->type = BLE_ADDR_RANDOM;

    rc = ble_hs_hci_rand(out_addr->val, 6);
    if (rc != 0) {
        return rc;
    }

    if (nrpa) {
        out_addr->val[5] &= ~0xc0;
    } else {
        out_addr->val[5] |= 0xc0;
    }

    return 0;
}

int
ble_hs_id_set_rnd(const uint8_t *rnd_addr)
{
    uint8_t addr_type_byte;
    int rc;
    int ones;

    ble_hs_lock();

    /* Make sure random part of rnd_addr is not all ones or zeros. Reference:
     * Core v5.0, Vol 6, Part B, section 1.3.2.1 */
    addr_type_byte = rnd_addr[5] & 0xc0;

    /* count bits set to 1 in random part of address */
    ones = __builtin_popcount(rnd_addr[0]);
    ones += __builtin_popcount(rnd_addr[1]);
    ones += __builtin_popcount(rnd_addr[2]);
    ones += __builtin_popcount(rnd_addr[3]);
    ones += __builtin_popcount(rnd_addr[4]);
    ones += __builtin_popcount(rnd_addr[5] & 0x3f);

    if ((addr_type_byte != 0x00 && addr_type_byte != 0xc0) ||
            (ones == 0 || ones == 46)) {
        rc = BLE_HS_EINVAL;
        goto done;
    }

    rc = ble_hs_hci_util_set_random_addr(rnd_addr);
    if (rc != 0) {
        goto done;
    }

    memcpy(ble_hs_id_rnd, rnd_addr, 6);

done:
    ble_hs_unlock();
    return rc;
}

/**
 * Retrieves one of the device's identity addresses.  The device can have two
 * identity addresses: one public and one random.  The id_addr_type argument
 * specifies which of these two addresses to retrieve.
 *
 * @param id_addr_type          The type of identity address to retrieve.
 *                                  Valid values are:
 *                                      o BLE_ADDR_PUBLIC
 *                                      o BLE_ADDR_RANDOM
 * @param out_id_addr           On success, this is reseated to point to the
 *                                  retrieved 6-byte identity address.  Pass
 *                                  NULL if you do not require this
 *                                  information.

 * @param out_is_nrpa           On success, the pointed-to value indicates
 *                                  whether the retrieved address is a
 *                                  non-resolvable private address.  Pass NULL
 *                                  if you do not require this information.
 *
 * @return                      0 on success;
 *                              BLE_HS_EINVAL if an invalid address type was
 *                                  specified;
 *                              BLE_HS_ENOADDR if the device does not have an
 *                                  identity address of the requested type;
 *                              Other BLE host core code on error.
 */
int
ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr,
               int *out_is_nrpa)
{
    const uint8_t *id_addr;
    int nrpa;

    BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());

    switch (id_addr_type) {
    case BLE_ADDR_PUBLIC:
        id_addr = ble_hs_id_pub;
        nrpa = 0;
        break;

    case BLE_ADDR_RANDOM:
        id_addr = ble_hs_id_rnd;
        nrpa = (ble_hs_id_rnd[5] & 0xc0) == 0;
        break;

    default:
        return BLE_HS_EINVAL;
    }

    if (memcmp(id_addr, ble_hs_misc_null_addr, 6) == 0) {
        return BLE_HS_ENOADDR;
    }

    if (out_id_addr != NULL) {
        *out_id_addr = id_addr;
    }
    if (out_is_nrpa != NULL) {
        *out_is_nrpa = nrpa;
    }

    return 0;
}

int
ble_hs_id_copy_addr(uint8_t id_addr_type, uint8_t *out_id_addr,
                    int *out_is_nrpa)
{
    const uint8_t *addr;
    int rc;

    ble_hs_lock();

    rc = ble_hs_id_addr(id_addr_type, &addr, out_is_nrpa);
    if (rc == 0 && out_id_addr != NULL) {
        memcpy(out_id_addr, addr, 6);
    }

    ble_hs_unlock();

    return rc;
}

static int
ble_hs_id_addr_type_usable(uint8_t own_addr_type)
{
    uint8_t id_addr_type;
    int nrpa;
    int rc;

    switch (own_addr_type) {
    case BLE_OWN_ADDR_PUBLIC:
    case BLE_OWN_ADDR_RANDOM:
        rc = ble_hs_id_addr(own_addr_type, NULL, NULL);
        if (rc != 0) {
            return rc;
        }
        break;

    case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT:
    case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT:
        id_addr_type = ble_hs_misc_own_addr_type_to_id(own_addr_type);
        rc = ble_hs_id_addr(id_addr_type, NULL, &nrpa);
        if (rc != 0) {
            return rc;
        }
        if (nrpa) {
            return BLE_HS_ENOADDR;
        }
        break;

    default:
        return BLE_HS_EINVAL;
    }

    return 0;
}

int
ble_hs_id_use_addr(uint8_t own_addr_type)
{
    int rc;

    rc = ble_hs_id_addr_type_usable(own_addr_type);
    if (rc != 0) {
        return rc;
    }

    /* If privacy is being used, make sure RPA rotation is in effect. */
    if (own_addr_type == BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT ||
        own_addr_type == BLE_OWN_ADDR_RPA_RANDOM_DEFAULT) {

        rc = ble_hs_pvcy_ensure_started();
        if (rc != 0) {
            return rc;
        }
    }

    return 0;
}

int
ble_hs_id_infer_auto(int privacy, uint8_t *out_addr_type)
{
    static const uint8_t pub_addr_types[] = {
        BLE_OWN_ADDR_RANDOM,
        BLE_OWN_ADDR_PUBLIC,
    };
    static const uint8_t priv_addr_types[] = {
        BLE_OWN_ADDR_RPA_RANDOM_DEFAULT,
        BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT,
    };
    const uint8_t *addr_types;
    uint8_t addr_type;
    int num_addr_types;
    int rc;
    int i;

    ble_hs_lock();

    if (privacy) {
        addr_types = priv_addr_types;
        num_addr_types = sizeof priv_addr_types / sizeof priv_addr_types[0];
    } else {
        addr_types = pub_addr_types;
        num_addr_types = sizeof pub_addr_types / sizeof pub_addr_types[0];
    }

    for (i = 0; i < num_addr_types; i++) {
        addr_type = addr_types[i];

        rc = ble_hs_id_addr_type_usable(addr_type);
        switch (rc) {
        case 0:
            *out_addr_type = addr_type;
            goto done;

        case BLE_HS_ENOADDR:
            break;

        default:
            goto done;
        }
    }

    rc = BLE_HS_ENOADDR;

done:
    ble_hs_unlock();
    return rc;
}

/**
 * Clears both the public and random addresses.  This function is necessary
 * when the controller loses its random address (e.g., on a stack reset).
 */
void
ble_hs_id_reset(void)
{
    memset(ble_hs_id_pub, 0, sizeof ble_hs_id_pub);
    memset(ble_hs_id_rnd, 0, sizeof ble_hs_id_pub);
}

/**
 * Clears random address. This function is necessary when the host wants to
 * clear random address.
 */
 void
 ble_hs_id_rnd_reset(void)
 {
    memset(ble_hs_id_rnd, 0, sizeof ble_hs_id_rnd);
 }
