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; }
static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, esp_phy_calibration_data_t* out_cal_data) { esp_err_t err; uint32_t cal_data_version; err = nvs_get_u32(handle, PHY_CAL_VERSION_KEY, &cal_data_version); if (err != ESP_OK) { ESP_LOGD(TAG, "%s: failed to get cal_version (0x%x)", __func__, err); return err; } uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16)); ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version); if (cal_data_version != cal_format_version) { ESP_LOGD(TAG, "%s: expected calibration data format %d, found %d", __func__, cal_format_version, cal_data_version); return ESP_FAIL; } uint8_t cal_data_mac[6]; size_t length = sizeof(cal_data_mac); err = nvs_get_blob(handle, PHY_CAL_MAC_KEY, cal_data_mac, &length); if (err != ESP_OK) { ESP_LOGD(TAG, "%s: failed to get cal_mac (0x%x)", __func__, err); return err; } if (length != sizeof(cal_data_mac)) { ESP_LOGD(TAG, "%s: invalid length of cal_mac (%d)", __func__, length); return ESP_ERR_INVALID_SIZE; } uint8_t sta_mac[6]; esp_efuse_mac_get_default(sta_mac); if (memcmp(sta_mac, cal_data_mac, sizeof(sta_mac)) != 0) { ESP_LOGE(TAG, "%s: calibration data MAC check failed: expected " \ MACSTR ", found " MACSTR, __func__, MAC2STR(sta_mac), MAC2STR(cal_data_mac)); return ESP_FAIL; } length = sizeof(*out_cal_data); err = nvs_get_blob(handle, PHY_CAL_DATA_KEY, out_cal_data, &length); if (err != ESP_OK) { ESP_LOGE(TAG, "%s: failed to get cal_data(0x%x)", __func__, err); return err; } if (length != sizeof(*out_cal_data)) { ESP_LOGD(TAG, "%s: invalid length of cal_data (%d)", __func__, length); return ESP_ERR_INVALID_SIZE; } return ESP_OK; }
static int get_config_size_from_flash(nvs_handle fp) { assert(fp != 0); esp_err_t err; char *keyname = osi_calloc(sizeof(CONFIG_KEY) + 1); if (!keyname){ LOG_ERROR("%s, malloc error\n", __func__); return 0; } size_t length = CONFIG_FILE_DEFAULE_LENGTH; size_t total_length = 0; uint16_t i = 0; snprintf(keyname, sizeof(CONFIG_KEY) + 1, "%s%d", CONFIG_KEY, 0); err = nvs_get_blob(fp, keyname, NULL, &length); if (err == ESP_ERR_NVS_NOT_FOUND) { osi_free(keyname); return 0; } if (err != ESP_OK) { LOG_ERROR("%s, error %d\n", __func__, err); osi_free(keyname); return 0; } total_length += length; while (length == CONFIG_FILE_MAX_SIZE) { length = CONFIG_FILE_DEFAULE_LENGTH; snprintf(keyname, sizeof(CONFIG_KEY) + 1, "%s%d", CONFIG_KEY, ++i); err = nvs_get_blob(fp, keyname, NULL, &length); if (err == ESP_ERR_NVS_NOT_FOUND) { break; } if (err != ESP_OK) { LOG_ERROR("%s, error %d\n", __func__, err); osi_free(keyname); return 0; } total_length += length; } osi_free(keyname); return total_length; }
/** * 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
/** * \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; }
static void config_parse(nvs_handle fp, config_t *config) { assert(fp != 0); assert(config != NULL); esp_err_t err; int line_num = 0; int err_code = 0; uint16_t i = 0; size_t length = CONFIG_FILE_DEFAULE_LENGTH; size_t total_length = 0; char *line = osi_calloc(1024); char *section = osi_calloc(1024); char *keyname = osi_calloc(sizeof(CONFIG_KEY) + 1); int buf_size = get_config_size_from_flash(fp); char *buf = osi_calloc(buf_size + 100); if (!line || !section || !buf || !keyname) { err_code |= 0x01; goto error; } snprintf(keyname, sizeof(CONFIG_KEY)+1, "%s%d", CONFIG_KEY, 0); err = nvs_get_blob(fp, keyname, buf, &length); if (err == ESP_ERR_NVS_NOT_FOUND) { goto error; } if (err != ESP_OK) { err_code |= 0x02; goto error; } total_length += length; while (length == CONFIG_FILE_MAX_SIZE) { length = CONFIG_FILE_DEFAULE_LENGTH; snprintf(keyname, sizeof(CONFIG_KEY) + 1, "%s%d", CONFIG_KEY, ++i); err = nvs_get_blob(fp, keyname, buf + CONFIG_FILE_MAX_SIZE * i, &length); if (err == ESP_ERR_NVS_NOT_FOUND) { break; } if (err != ESP_OK) { err_code |= 0x02; goto error; } total_length += length; } char *p_line_end; char *p_line_bgn = buf; strcpy(section, CONFIG_DEFAULT_SECTION); while ( (p_line_bgn < buf + total_length - 1) && (p_line_end = strchr(p_line_bgn, '\n'))) { // get one line int line_len = p_line_end - p_line_bgn; if (line_len > 1023) { LOG_WARN("%s exceed max line length on line %d.\n", __func__, line_num); break; } memcpy(line, p_line_bgn, line_len); line[line_len] = '\0'; p_line_bgn = p_line_end + 1; char *line_ptr = trim(line); ++line_num; // Skip blank and comment lines. if (*line_ptr == '\0' || *line_ptr == '#') { continue; } if (*line_ptr == '[') { size_t len = strlen(line_ptr); if (line_ptr[len - 1] != ']') { LOG_WARN("%s unterminated section name on line %d.\n", __func__, line_num); continue; } strncpy(section, line_ptr + 1, len - 2); section[len - 2] = '\0'; } else { char *split = strchr(line_ptr, '='); if (!split) { LOG_DEBUG("%s no key/value separator found on line %d.\n", __func__, line_num); continue; } *split = '\0'; config_set_string(config, section, trim(line_ptr), trim(split + 1), true); } } error: if (buf) { osi_free(buf); } if (line) { osi_free(line); } if (section) { osi_free(section); } if (keyname) { osi_free(keyname); } if (err_code) { LOG_ERROR("%s returned with err code: %d\n", __func__, err_code); } }