Esempio n. 1
0
/**
 * \brief Saves the random seed to EEPROM.
 *
 * During system startup, noise sources typically won't have accumulated
 * much entropy.  But startup is usually the time when the system most
 * needs to generate random data for session keys, IV's, and the like.
 *
 * The purpose of this function is to pass some of the accumulated entropy
 * from one session to the next after a loss of power.  Thus, once the system
 * has been running for a while it will get progressively better at generating
 * random values and the accumulated entropy will not be completely lost.
 *
 * Normally it isn't necessary to call save() directly.  The loop() function
 * will automatically save the seed on a periodic basis (default of 1 hour).
 *
 * The seed that is saved is generated in such a way that it cannot be used
 * to predict random values that were generated previously or subsequently
 * in the current session.  So a compromise of the EEPROM contents of a
 * captured device should not result in compromise of random values
 * that have already been generated.  However, if power is lost and the
 * system restarted, then there will be a short period of time where the
 * random state will be predictable from the seed.  For this reason it is
 * very important to stir() in new noise data at startup.
 *
 * \sa loop(), stir()
 */
void RNGClass::save()
{
    // Generate random data from the current state and save
    // that as the seed.  Then force a rekey.
    ++(block[12]);
    ChaCha::hashCore(stream, block, RNG_ROUNDS);
#if defined(RNG_EEPROM)
    // We shorten the seed from 48 bytes to 47 to leave room for
    // the CRC-8 value.  We do this to align the data on an 8-byte
    // boundary in EERPOM.
    int address = RNG_EEPROM_ADDRESS;
    eeprom_write_block(stream, (void *)address, SEED_SIZE - 1);
    eeprom_write_byte((uint8_t *)(address + SEED_SIZE - 1),
                      crypto_crc8('S', stream, SEED_SIZE - 1));
#elif defined(RNG_DUE_TRNG)
    unsigned posn;
    ((uint32_t *)(RNG_SEED_ADDR))[0] = crypto_crc8('S', stream, SEED_SIZE);
    for (posn = 0; posn < 12; ++posn)
        ((uint32_t *)(RNG_SEED_ADDR))[posn + 1] = stream[posn];
    for (posn = 13; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn)
        ((uint32_t *)(RNG_SEED_ADDR))[posn + 13] = 0xFFFFFFFF;
    eraseAndWriteSeed();
#elif defined(RNG_ESP_NVS)
    // Save the seed into ESP non-volatile storage (NVS).
    nvs_handle handle = 0;
    if (nvs_open("rng", NVS_READWRITE, &handle) == 0) {
        nvs_erase_all(handle);
        nvs_set_blob(handle, "seed", stream, SEED_SIZE);
        nvs_commit(handle);
        nvs_close(handle);
    }
#endif
    rekey();
    timer = millis();
}
Esempio n. 2
0
File: ssl.c Progetto: kubecz3k/godot
int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf,
	       lws_filepos_t *amount)
{
	nvs_handle nvh;
	size_t s;
	int n = 0;

	ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh));
	if (nvs_get_blob(nvh, filename, NULL, &s) != ESP_OK) {
		n = 1;
		goto bail;
	}
	*buf = lws_malloc(s, "alloc_file");
	if (!*buf) {
		n = 2;
		goto bail;
	}
	if (nvs_get_blob(nvh, filename, (char *)*buf, &s) != ESP_OK) {
		lws_free(*buf);
		n = 1;
		goto bail;
	}

	*amount = s;

bail:
	nvs_close(nvh);

	return n;
}
Esempio n. 3
0
void ESP32_Set_NVS_Status(esp_hardware_esp32_t hardware, bool enable){
	nvs_handle hardwareHandle; uint32_t status;
	if(enable) status = 1; else status = 0;
	nvs_open("nvs",NVS_READWRITE,&hardwareHandle);
	nvs_set_u32(hardwareHandle,ESP32_hardwareName(hardware),status);
	nvs_close(hardwareHandle);
}  
Esempio n. 4
0
config_t *config_new(const char *filename)
{
    assert(filename != NULL);

    config_t *config = config_new_empty();
    if (!config) {
        return NULL;
    }

    esp_err_t err;
    nvs_handle fp;
    err = nvs_open(filename, NVS_READWRITE, &fp);
    if (err != ESP_OK) {
        if (err == ESP_ERR_NVS_NOT_INITIALIZED) {
            LOG_ERROR("%s: NVS not initialized. "
                      "Call nvs_flash_init before initializing bluetooth.", __func__);
        } else {
            LOG_ERROR("%s unable to open NVS namespace '%s'\n", __func__, filename);
        }
        config_free(config);
        return NULL;
    }

    config_parse(fp, config);
    nvs_close(fp);
    return config;
}
Esempio n. 5
0
/**
 * Save our connection info for retrieval on a subsequent restart.
 */
static void saveConnectionInfo(connection_info_t *pConnectionInfo) {
	nvs_handle handle;
	ESP_ERROR_CHECK(nvs_open(BOOTWIFI_NAMESPACE, NVS_READWRITE, &handle));
	ESP_ERROR_CHECK(nvs_set_blob(handle, KEY_CONNECTION_INFO, pConnectionInfo,
			sizeof(connection_info_t)));
	ESP_ERROR_CHECK(nvs_set_u32(handle, KEY_VERSION, g_version));
	ESP_ERROR_CHECK(nvs_commit(handle));
	nvs_close(handle);
} // setConnectionInfo
Esempio n. 6
0
bool ESP32_Get_NVS_Status(esp_hardware_esp32_t hardware){
	esp_err_t err;nvs_handle hardwareHandle; uint32_t status;
	nvs_open("nvs",NVS_READWRITE,&hardwareHandle);
	err = nvs_get_u32(hardwareHandle,ESP32_hardwareName(hardware),&status);
	if(err) {
		status = ESP32HARDWAREDEFAULT;
		nvs_set_u32(hardwareHandle,ESP32_hardwareName(hardware),ESP32HARDWAREDEFAULT);
	}
	nvs_close(hardwareHandle);
	return (bool) status;
}
Esempio n. 7
0
esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data)
{
    nvs_handle handle;
    esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READWRITE, &handle);
    if (err != ESP_OK) {
        ESP_LOGD(TAG, "%s: failed to open NVS namespace (0x%x)", __func__, err);
        return err;
    }
    else {
        err = store_cal_data_to_nvs_handle(handle, cal_data);
        nvs_close(handle);
        return err;
    }
}
Esempio n. 8
0
void dhcp_ip_addr_erase(void *netif)
{
    nvs_handle nvs;
    struct netif *net = (struct netif *)netif;
    esp_interface_t netif_id = tcpip_adapter_get_esp_if(net);

    if(VALID_NETIF_ID(netif_id)) {
        if (nvs_open(DHCP_NAMESPACE, NVS_READWRITE, &nvs) == ESP_OK) {
            nvs_erase_key(nvs, interface_key[netif_id]);
            nvs_commit(nvs);
            nvs_close(nvs);
        }
    }
}
Esempio n. 9
0
/**
 * Retrieve the connection info.  A rc==0 means ok.
 */
static int getConnectionInfo(connection_info_t *pConnectionInfo) {
	nvs_handle handle;
	size_t size;
	esp_err_t err;
	uint32_t version;
	err = nvs_open(BOOTWIFI_NAMESPACE, NVS_READWRITE, &handle);
	if (err != 0) {
		ESP_LOGE(tag, "nvs_open: %x", err);
		return -1;
	}

	// Get the version that the data was saved against.
	err = nvs_get_u32(handle, KEY_VERSION, &version);
	if (err != ESP_OK) {
		ESP_LOGD(tag, "No version record found (%d).", err);
		nvs_close(handle);
		return -1;
	}

	// Check the versions match
	if ((version & 0xff00) != (g_version & 0xff00)) {
		ESP_LOGD(tag, "Incompatible versions ... current is %x, found is %x", version, g_version);
		nvs_close(handle);
		return -1;
	}

	size = sizeof(connection_info_t);
	err = nvs_get_blob(handle, KEY_CONNECTION_INFO, pConnectionInfo, &size);
	if (err != ESP_OK) {
		ESP_LOGD(tag, "No connection record found (%d).", err);
		nvs_close(handle);
		return -1;
	}
	if (err != ESP_OK) {
		ESP_LOGE(tag, "nvs_open: %x", err);
		nvs_close(handle);
		return -1;
	}

	// Cleanup
	nvs_close(handle);

	// Do a sanity check on the SSID
	if (strlen(pConnectionInfo->ssid) == 0) {
		ESP_LOGD(tag, "NULL ssid detected");
		return -1;
	}
	return 0;
} // getConnectionInfo
Esempio n. 10
0
esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_data)
{
    nvs_handle handle;
    esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READONLY, &handle);
    if (err == ESP_ERR_NVS_NOT_INITIALIZED) {
        ESP_LOGE(TAG, "%s: NVS has not been initialized. "
                "Call nvs_flash_init before starting WiFi/BT.", __func__);
    } else if (err != ESP_OK) {
        ESP_LOGD(TAG, "%s: failed to open NVS namespace (0x%x)", __func__, err);
        return err;
    }
    err = load_cal_data_from_nvs_handle(handle, out_cal_data);
    nvs_close(handle);
    return err;
}
Esempio n. 11
0
void dhcp_ip_addr_store(void *netif)
{
    nvs_handle nvs;
    struct netif *net = (struct netif *)netif;
    struct dhcp *dhcp = netif_dhcp_data(net);
    uint32_t ip_addr = dhcp->offered_ip_addr.addr;
    esp_interface_t netif_id = tcpip_adapter_get_esp_if(net);

    if(VALID_NETIF_ID(netif_id)) {
        if (restored_ip_addr[netif_id] != ip_addr) {
            if (nvs_open(DHCP_NAMESPACE, NVS_READWRITE, &nvs) == ESP_OK) {
                nvs_set_u32(nvs, interface_key[netif_id], ip_addr);
                nvs_commit(nvs);
                nvs_close(nvs);
            }
        }
    }
}
Esempio n. 12
0
bool dhcp_ip_addr_restore(void *netif)
{
    nvs_handle nvs;
    bool err = false;
    struct netif *net = (struct netif *)netif;
    struct dhcp *dhcp = netif_dhcp_data(net);
    esp_interface_t netif_id = tcpip_adapter_get_esp_if(net);

    if(VALID_NETIF_ID(netif_id)) {
        uint32_t *ip_addr = &dhcp->offered_ip_addr.addr;
        if (nvs_open(DHCP_NAMESPACE, NVS_READONLY, &nvs) == ESP_OK) {
            if (nvs_get_u32(nvs, interface_key[netif_id], ip_addr) == ESP_OK) {
                restored_ip_addr[netif_id] = *ip_addr;
                err = true;
            }
            nvs_close(nvs);
        }
    }
    return err;
}
Esempio n. 13
0
/**
 * \brief Destroys the data in the random number pool and the saved seed
 * in EEPROM.
 *
 * This function attempts to throw away any data that could theoretically be
 * used to predict previous and future outputs of the random number generator
 * if the device is captured, sold, or otherwise compromised.
 *
 * After this function is called, begin() must be called again to
 * re-initialize the random number generator.
 *
 * \note The rand() and save() functions take some care to manage the
 * random number pool in a way that makes prediction of past outputs from a
 * captured state very difficult.  Future outputs may be predictable if
 * noise or other high-entropy data is not mixed in with stir() on a
 * regular basis.
 *
 * \sa begin()
 */
void RNGClass::destroy()
{
    clean(block);
    clean(stream);
#if defined(RNG_EEPROM)
    int address = RNG_EEPROM_ADDRESS;
    for (int posn = 0; posn < SEED_SIZE; ++posn)
        eeprom_write_byte((uint8_t *)(address + posn), 0xFF);
#elif defined(RNG_DUE_TRNG)
    for (unsigned posn = 0; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn)
        ((uint32_t *)(RNG_SEED_ADDR))[posn] = 0xFFFFFFFF;
    eraseAndWriteSeed();
#elif defined(RNG_ESP_NVS)
    nvs_handle handle = 0;
    if (nvs_open("rng", NVS_READWRITE, &handle) == 0) {
        nvs_erase_all(handle);
        nvs_commit(handle);
        nvs_close(handle);
    }
#endif
    initialized = 0;
}
Esempio n. 14
0
/**
 * \brief Initializes the random number generator.
 *
 * \param tag A string that is stirred into the random pool at startup;
 * usually this should be a value that is unique to the application and
 * version such as "MyApp 1.0" so that different applications do not
 * generate the same sequence of values upon first boot.
 *
 * This function should be followed by calls to addNoiseSource() to
 * register the application's noise sources.
 *
 * \sa addNoiseSource(), stir(), save()
 */
void RNGClass::begin(const char *tag)
{
    // Bail out if we have already done this.
    if (initialized)
        return;

    // Initialize the ChaCha20 input block from the saved seed.
    memcpy_P(block, tagRNG, sizeof(tagRNG));
    memcpy_P(block + 4, initRNG, sizeof(initRNG));
#if defined(RNG_EEPROM)
    int address = RNG_EEPROM_ADDRESS;
    eeprom_read_block(stream, (const void *)address, SEED_SIZE);
    if (crypto_crc8('S', stream, SEED_SIZE - 1) ==
            ((const uint8_t *)stream)[SEED_SIZE - 1]) {
        // We have a saved seed: XOR it with the initialization block.
        // Note: the CRC-8 value is included.  No point throwing it away.
        for (int posn = 0; posn < 12; ++posn)
            block[posn + 4] ^= stream[posn];
    }
#elif defined(RNG_DUE_TRNG)
    // Do we have a seed saved in the last page of flash memory on the Due?
    if (crypto_crc8('S', ((const uint32_t *)RNG_SEED_ADDR) + 1, SEED_SIZE)
            == ((const uint32_t *)RNG_SEED_ADDR)[0]) {
        // XOR the saved seed with the initialization block.
        for (int posn = 0; posn < 12; ++posn)
            block[posn + 4] ^= ((const uint32_t *)RNG_SEED_ADDR)[posn + 1];
    }

    // If the device has just been reprogrammed, there will be no saved seed.
    // XOR the initialization block with some output from the CPU's TRNG
    // to permute the state in a first boot situation after reprogramming.
    pmc_enable_periph_clk(ID_TRNG);
    REG_TRNG_CR = TRNG_CR_KEY(0x524E47) | TRNG_CR_ENABLE;
    REG_TRNG_IDR = TRNG_IDR_DATRDY; // Disable interrupts - we will poll.
    mixTRNG();
#endif
#if defined(RNG_ESP_NVS)
    // Do we have a seed saved in ESP non-volatile storage (NVS)?
    nvs_handle handle = 0;
    if (nvs_open("rng", NVS_READONLY, &handle) == 0) {
        size_t len = 0;
        if (nvs_get_blob(handle, "seed", NULL, &len) == 0 && len == SEED_SIZE) {
            uint32_t seed[12];
            if (nvs_get_blob(handle, "seed", seed, &len) == 0) {
                for (int posn = 0; posn < 12; ++posn)
                    block[posn + 4] ^= seed[posn];
            }
            clean(seed);
        }
        nvs_close(handle);
    }
#endif
#if defined(RNG_WORD_TRNG)
    // Mix in some output from a word-based TRNG to initialize the state.
    mixTRNG();
#endif

    // No entropy credits for the saved seed.
    credits = 0;

    // Trigger an automatic save once the entropy credits max out.
    firstSave = 1;

    // Rekey the random number generator immediately.
    rekey();

    // Stir in the supplied tag data but don't credit any entropy to it.
    if (tag)
        stir((const uint8_t *)tag, strlen(tag));

#if defined(RNG_DUE_TRNG)
    // Stir in the unique identifier for the CPU so that different
    // devices will give different outputs even without seeding.
    stirUniqueIdentifier();
#elif defined(ESP8266)
    // ESP8266's have a 32-bit CPU chip ID and 32-bit flash chip ID
    // that we can use as a device unique identifier.
    uint32_t ids[2];
    ids[0] = ESP.getChipId();
    ids[1] = ESP.getFlashChipId();
    stir((const uint8_t *)ids, sizeof(ids));
#elif defined(ESP32)
    // ESP32's have a MAC address that can be used as a device identifier.
    uint64_t mac = ESP.getEfuseMac();
    stir((const uint8_t *)&mac, sizeof(mac));
#else
    // AVR devices don't have anything like a serial number so it is
    // difficult to make every device unique.  Use the compilation
    // time and date to provide a little randomness across applications
    // if not across devices running the same pre-compiled application.
    tag = __TIME__ __DATE__;
    stir((const uint8_t *)tag, strlen(tag));
#endif

#if defined(RNG_WATCHDOG)
    // Disable interrupts and reset the watchdog.
    cli();
    wdt_reset();

    // Clear the "reset due to watchdog" flag.
    MCUSR &= ~(1 << WDRF);

    // Enable the watchdog with the smallest duration (16ms)
    // and interrupt-only mode.
    _WD_CONTROL_REG |= (1 << _WD_CHANGE_BIT) | (1 << WDE);
    _WD_CONTROL_REG = (1 << WDIE);

    // Re-enable interrupts.  The watchdog should be running.
    sei();
#endif

    // Re-save the seed to obliterate the previous value and to ensure
    // that if the system is reset without a call to save() that we won't
    // accidentally generate the same sequence of random data again.
    save();

    // The RNG has now been initialized.
    initialized = 1;
}
Esempio n. 15
0
bool config_save(const config_t *config, const char *filename)
{
    assert(config != NULL);
    assert(filename != NULL);
    assert(*filename != '\0');

    esp_err_t err;
    int err_code = 0;
    nvs_handle fp;
    char *line = osi_calloc(1024);
    char *keyname = osi_calloc(sizeof(CONFIG_KEY) + 1);
    int config_size = get_config_size(config);
    char *buf = osi_calloc(config_size + 100);
    if (!line || !buf || !keyname) {
        err_code |= 0x01;
        goto error;
    }

    err = nvs_open(filename, NVS_READWRITE, &fp);
    if (err != ESP_OK) {
        if (err == ESP_ERR_NVS_NOT_INITIALIZED) {
            LOG_ERROR("%s: NVS not initialized. "
                      "Call nvs_flash_init before initializing bluetooth.", __func__);
        }
        err_code |= 0x02;
        goto error;
    }

    int w_cnt, w_cnt_total = 0;
    for (const list_node_t *node = list_begin(config->sections); node != list_end(config->sections); node = list_next(node)) {
        const section_t *section = (const section_t *)list_node(node);
        w_cnt = snprintf(line, 1024, "[%s]\n", section->name);
        LOG_DEBUG("section name: %s, w_cnt + w_cnt_total = %d\n", section->name, w_cnt + w_cnt_total);
        memcpy(buf + w_cnt_total, line, w_cnt);
        w_cnt_total += w_cnt;

        for (const list_node_t *enode = list_begin(section->entries); enode != list_end(section->entries); enode = list_next(enode)) {
            const entry_t *entry = (const entry_t *)list_node(enode);
            LOG_DEBUG("(key, val): (%s, %s)\n", entry->key, entry->value);
            w_cnt = snprintf(line, 1024, "%s = %s\n", entry->key, entry->value);
            LOG_DEBUG("%s, w_cnt + w_cnt_total = %d", __func__, w_cnt + w_cnt_total);
            memcpy(buf + w_cnt_total, line, w_cnt);
            w_cnt_total += w_cnt;
        }

        // Only add a separating newline if there are more sections.
        if (list_next(node) != list_end(config->sections)) {
            buf[w_cnt_total] = '\n';
            w_cnt_total += 1;
        } else {
            break;
        }
    }
    buf[w_cnt_total] = '\0';
    if (w_cnt_total < CONFIG_FILE_MAX_SIZE) {
        snprintf(keyname, sizeof(CONFIG_KEY)+1, "%s%d", CONFIG_KEY, 0);
        err = nvs_set_blob(fp, keyname, buf, w_cnt_total);
        if (err != ESP_OK) {
            nvs_close(fp);
            err_code |= 0x04;
            goto error;
        }
    }else {
        uint count = (w_cnt_total / CONFIG_FILE_MAX_SIZE);
        for (int i = 0; i <= count; i++)
        {
            snprintf(keyname, sizeof(CONFIG_KEY)+1, "%s%d", CONFIG_KEY, i);
            if (i == count) {
                err = nvs_set_blob(fp, keyname, buf + i*CONFIG_FILE_MAX_SIZE, w_cnt_total - i*CONFIG_FILE_MAX_SIZE);
                LOG_DEBUG("save keyname = %s, i = %d, %d\n", keyname, i, w_cnt_total - i*CONFIG_FILE_MAX_SIZE);
            }else {
                err = nvs_set_blob(fp, keyname, buf + i*CONFIG_FILE_MAX_SIZE, CONFIG_FILE_MAX_SIZE);
                LOG_DEBUG("save keyname = %s, i = %d, %d\n", keyname, i, CONFIG_FILE_MAX_SIZE);
            }
            if (err != ESP_OK) {
                nvs_close(fp);
                err_code |= 0x04;
                goto error;
            }
        }
    }

    err = nvs_commit(fp);
    if (err != ESP_OK) {
        nvs_close(fp);
        err_code |= 0x08;
        goto error;
    }

    nvs_close(fp);
    osi_free(line);
    osi_free(buf);
    osi_free(keyname);
    return true;

error:
    if (buf) {
        osi_free(buf);
    }
    if (line) {
        osi_free(line);
    }
    if (keyname) {
        osi_free(keyname);
    }
    if (err_code) {
        LOG_ERROR("%s, err_code: 0x%x\n", __func__, err_code);
    }
    return false;
}