stm32f4xx_eedata: define & implement eedata api
also migrate aes key lookup to it
Change-Id: I3574acedce3747d8d848b48e9cbc9c01e1a4e304
diff --git a/firmware/inc/eeData.h b/firmware/inc/eeData.h
new file mode 100644
index 0000000..64b8185
--- /dev/null
+++ b/firmware/inc/eeData.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef _EEDATA_H_
+#define _EEDATA_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/*
+ * EEDATA allows storage of data in a persistent area that survives reboots and OS updates.
+ * Each data piece has a name and stores 0..EE_DATA_LEN_MAX bytes of data. The name is a
+ * non-zero number in the range 0..EE_DATA_NAME_MAX - 1. All names below EE_DATA_FIRST_USER
+ * are reserved for OS purposes and are not accessible using the external-app-visible API.
+ * To store an EEDATA item, use eeDataSet(). Setting the buffer to NULL will delete an
+ * existing item and not replace it. Otherwise an item is replaced. Return value is success
+ * (deleting a non-existent item always suceeds). You can use eeDataGet() to get items. It
+ * will return true if an item exists. If called with buf set to NULL and szP not NULL,
+ * *szP will be filled with its size. Else if buf and szP are both not NULL, up to *szP
+ * bytes will be stored into buf, and *szP will be updated with the number of bytes written.
+ * True is returned if the data item exists at all, else false is. For encryption keys, we
+ * [ab]use eeDataGetAllVersions to get all keys (as each has the same name).
+ */
+
+
+
+#define EE_DATA_NAME_MAX 0x000FFFFF
+#define EE_DATA_LEN_MAX 0x00000FFF //in bytes
+#define EE_DATA_FIRST_USER 0x00000100
+
+
+bool eeDataGet(uint32_t name, void *buf, uint32_t *szP);
+bool eeDataSet(uint32_t name, const void *buf, uint32_t len);
+
+//allow getting old "versions". Set state to NULL initially, call till you get false
+bool eeDataGetAllVersions(uint32_t name, void *buf, uint32_t *szP, void **stateP);
+bool eeDataEraseOldVersion(uint32_t name, void *state); //state == state BEFORE call to eeDataGetAllVersions that found the version you want gone
+
+//predefined key types
+
+#define EE_DATA_NAME_ENCR_KEY 1
+
+
+
+#endif
+
diff --git a/firmware/inc/platform/stm32f4xx/bl.h b/firmware/inc/platform/stm32f4xx/bl.h
index cd43fca..9824493 100644
--- a/firmware/inc/platform/stm32f4xx/bl.h
+++ b/firmware/inc/platform/stm32f4xx/bl.h
@@ -80,6 +80,7 @@
//flash
bool (*blProgramShared)(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2);
bool (*blEraseShared)(uint32_t key1, uint32_t key2);
+ bool (*blProgramEe)(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2);
//security data
const uint32_t* (*blGetPubKeysInfo)(uint32_t *numKeys);
diff --git a/firmware/inc/platform/stm32f4xx/eeData.h b/firmware/inc/platform/stm32f4xx/eeData.h
new file mode 100644
index 0000000..6cba150
--- /dev/null
+++ b/firmware/inc/platform/stm32f4xx/eeData.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef _STM32F4xx_EEDATA_H_
+#define _STM32F4xx_EEDATA_H_
+
+#include <eeData.h>
+#include <seos.h>
+
+struct Stm32f4xxEedataHdr {
+ uint32_t info;
+};
+
+struct Stm32f4xxEedataEncrKey {
+ struct Stm32f4xxEedataHdr hdr;
+ struct SeosEedataEncrKeyData data;
+} __attribute__((packed));
+
+
+#define PREPOPULATED_ENCR_KEY(name, keyid, ...) \
+ const struct Stm32f4xxEedataEncrKey __attribute__ ((section (".eedata"))) __EE__ ## name = { { EE_DATA_NAME_ENCR_KEY + sizeof(struct SeosEedataEncrKeyData) * (EE_DATA_NAME_MAX + 1)}, {keyid, {__VA_ARGS__}}}
+
+
+
+#endif
diff --git a/firmware/inc/platform/stm32f4xx/plat.h b/firmware/inc/platform/stm32f4xx/plat.h
index fdefbcd..6ffb0af 100644
--- a/firmware/inc/platform/stm32f4xx/plat.h
+++ b/firmware/inc/platform/stm32f4xx/plat.h
@@ -39,17 +39,6 @@
Stm32sleepDevNum, //must be last always, and must be <= PLAT_MAX_SLEEP_DEVS
};
-struct StmPlatEeDataGeneric {
- uint32_t eeDataType : 20;
- uint32_t eeDataLen : 12; // not incl header
-} __attribute__((packed));
-
-struct StmPlatEeDataEncrKey {
- struct StmPlatEeDataGeneric hdr;
- uint64_t keyID;
- uint8_t key[32];
-} __attribute__((packed));
-
static inline const struct AppHdr* platGetInternalAppList(uint32_t *numAppsP)
{
extern const struct AppHdr __internal_app_start, __internal_app_end;
@@ -70,8 +59,6 @@
//used for dropbox
void* platGetPersistentRamStore(uint32_t *bytes);
-#define PREPOPULATED_ENCR_KEY(name, keyid, ...) \
- const struct StmPlatEeDataEncrKey __attribute__ ((section (".eedata"))) __EE__ ## name = { { EE_DATA_TYPE_ENCR_KEY, sizeof(struct StmPlatEeDataEncrKey) - sizeof(struct StmPlatEeDataGeneric)}, keyid, {__VA_ARGS__}}
#ifdef __cplusplus
}
diff --git a/firmware/inc/seos.h b/firmware/inc/seos.h
index b2554cd..9f6b1b1 100644
--- a/firmware/inc/seos.h
+++ b/firmware/inc/seos.h
@@ -41,8 +41,6 @@
#define OS_VER 0x0000
-#define EE_DATA_TYPE_ENCR_KEY 1
-
#define ENCR_KEY_GOOGLE_PREPOPULATED 1 // our key ID is 1
#define FIRST_VALID_TID 0x00000001
@@ -105,6 +103,11 @@
typedef void (*EventFreeF)(void* event);
+struct SeosEedataEncrKeyData {
+ uint64_t keyID;
+ uint8_t key[32];
+} __attribute__((packed));
+
/* ==== ABOUT THE "urgent" FLAG ====
*
* Do not set "urgent" unless you understand all the repercussions! What repercussions you might ask?
diff --git a/firmware/misc/platform/stm32f4xx/Makefile b/firmware/misc/platform/stm32f4xx/Makefile
index 3c7662e..37c9aba 100644
--- a/firmware/misc/platform/stm32f4xx/Makefile
+++ b/firmware/misc/platform/stm32f4xx/Makefile
@@ -49,6 +49,7 @@
src/platform/$(PLATFORM)/crc.c \
src/platform/$(PLATFORM)/hostIntf.c \
src/platform/$(PLATFORM)/apInt.c \
+ src/platform/$(PLATFORM)/eeData.c
#extra deps
DEPS += $(wildcard inc/platform/$(PLATFORM)/*.h)
diff --git a/firmware/src/nanohubCommand.c b/firmware/src/nanohubCommand.c
index d6323bd..b91b5f0 100644
--- a/firmware/src/nanohubCommand.c
+++ b/firmware/src/nanohubCommand.c
@@ -26,6 +26,7 @@
#include <hostIntf_priv.h>
#include <nanohubCommand.h>
#include <nanohubPacket.h>
+#include <eeData.h>
#include <seos.h>
#include <util.h>
#include <mpu.h>
@@ -141,23 +142,19 @@
static AppSecErr aesKeyAccessCbk(uint64_t keyIdx, void *keyBuf)
{
- extern const struct StmPlatEeDataGeneric __eedata_start;
- extern char __eedata_end[];
- const struct StmPlatEeDataGeneric *hdr;
- const struct StmPlatEeDataEncrKey *key;
+ struct SeosEedataEncrKeyData kd;
+ void *state = NULL;
- hdr = &__eedata_start;
- while (((uintptr_t)&__eedata_end) - ((uintptr_t)hdr) >= sizeof(struct StmPlatEeDataGeneric) && hdr->eeDataType != 0xFFFFF) {
- switch (hdr->eeDataType) {
- case EE_DATA_TYPE_ENCR_KEY:
- key = (const struct StmPlatEeDataEncrKey *)hdr;
- if (key->keyID == keyIdx) {
- memcpy(keyBuf, key->key, sizeof(key->key));
- return APP_SEC_NO_ERROR;
- }
+ while(1) {
+ uint32_t sz = sizeof(struct SeosEedataEncrKeyData);
+
+ if (!eeDataGetAllVersions(EE_DATA_NAME_ENCR_KEY, &kd, &sz, &state))
break;
+
+ if (sz == sizeof(struct SeosEedataEncrKeyData) && kd.keyID == keyIdx) {
+ memcpy(keyBuf, kd.key, sizeof(kd.key));
+ return APP_SEC_NO_ERROR;
}
- hdr = (const struct StmPlatEeDataGeneric*)(((((uintptr_t)hdr) + sizeof(struct StmPlatEeDataGeneric) + hdr->eeDataLen) + 3) &~ 3);
}
return APP_SEC_KEY_NOT_FOUND;
diff --git a/firmware/src/platform/stm32f4xx/bl.c b/firmware/src/platform/stm32f4xx/bl.c
index bdb1b57..916ad99 100644
--- a/firmware/src/platform/stm32f4xx/bl.c
+++ b/firmware/src/platform/stm32f4xx/bl.c
@@ -506,7 +506,7 @@
}
BOOTLOADER
-static bool blExtApiProgramSharedArea(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2)
+static bool blExtApiProgramTypedArea(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2, uint32_t type)
{
const uint32_t sector_cnt = sizeof(mBlFlashTable) / sizeof(struct blFlashTable);
uint32_t i;
@@ -517,7 +517,7 @@
dst < (mBlFlashTable[i].address + mBlFlashTable[i].length)) ||
(dst < mBlFlashTable[i].address &&
(dst + length > mBlFlashTable[i].address))) {
- if (mBlFlashTable[i].type != BL_FLASH_SHARED)
+ if (mBlFlashTable[i].type != type)
return false;
}
}
@@ -526,6 +526,18 @@
}
BOOTLOADER
+static bool blExtApiProgramSharedArea(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2)
+{
+ return blExtApiProgramTypedArea(dst, src, length, key1, key2, BL_FLASH_SHARED);
+}
+
+BOOTLOADER
+static bool blExtApiProgramEe(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2)
+{
+ return blExtApiProgramTypedArea(dst, src, length, key1, key2, BL_FLASH_EEDATA);
+}
+
+BOOTLOADER
static bool blExtApiEraseSharedArea(uint32_t key1, uint32_t key2)
{
struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
@@ -650,6 +662,7 @@
.blGetSnum = &blExtApiGetSnum,
.blProgramShared = &blExtApiProgramSharedArea,
.blEraseShared = &blExtApiEraseSharedArea,
+ .blProgramEe = &blExtApiProgramEe,
.blGetPubKeysInfo = &blExtApiGetRsaKeyInfo,
.blRsaPubOpIterative = &_rsaPubOpIterative,
.blSha2init = &_sha2init,
diff --git a/firmware/src/platform/stm32f4xx/eeData.c b/firmware/src/platform/stm32f4xx/eeData.c
new file mode 100644
index 0000000..bde9f9f
--- /dev/null
+++ b/firmware/src/platform/stm32f4xx/eeData.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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 <plat/inc/bl.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdint.h>
+#include <eeData.h>
+
+
+extern uint32_t __eedata_start[], __eedata_end[];
+
+//STM32F4xx eedata stores data in 4-byte aligned chunks
+
+static void* eeFind(uint32_t nameToFind, uint32_t startOffset, bool findFirst, uint32_t *szP)
+{
+ uint32_t *p = __eedata_start + startOffset;
+ void *foundData = NULL;
+
+ //find the last incarnation of "name" in flash area
+ while (p < __eedata_end) {
+ uint32_t info = *p++;
+ uint32_t name = info & EE_DATA_NAME_MAX;
+ uint32_t sz = info / (EE_DATA_NAME_MAX + 1);
+ void *data = p;
+
+ //skip over to next data chunk header
+ p += (sz + 3) / 4;
+
+ //check for a match
+ if (nameToFind == name) {
+ *szP = sz;
+ foundData = data;
+
+ if (findFirst)
+ break;
+ }
+
+ //check for ending condition (name == max)
+ if (name == EE_DATA_NAME_MAX)
+ break;
+ }
+
+ return foundData;
+}
+
+static bool eeIsValidName(uint32_t name)
+{
+ return name && name < EE_DATA_NAME_MAX;
+}
+
+static bool eeDataGetEx(uint32_t name, uint32_t *offsetP, bool first, void *buf, uint32_t *szP)
+{
+ uint32_t sz = 0;
+ void *data;
+
+ if (!eeIsValidName(name))
+ return false;
+
+ //find the data item
+ data = eeFind(name, *offsetP, first, &sz);
+ if (!data)
+ return false;
+
+ if (buf && szP) { //get the data
+ if (sz > *szP)
+ sz = *szP;
+ *szP = sz;
+ memcpy(buf, data, sz);
+ }
+ else if (szP) //get size
+ *szP = sz;
+
+ *offsetP = (uint32_t)data + ((sz + 3) &~ 3);
+
+ return true;
+}
+
+bool eeDataGet(uint32_t name, void *buf, uint32_t *szP)
+{
+ uint32_t offset = 0;
+
+ return eeDataGetEx(name, &offset, false, buf, szP);
+}
+
+bool eeDataGetAllVersions(uint32_t name, void *buf, uint32_t *szP, void **stateP)
+{
+ uint32_t offset = *(uint32_t*)stateP;
+ bool ret;
+
+ ret = eeDataGetEx(name, &offset, true, buf, szP);
+ *(uint32_t*)stateP = offset;
+
+ return ret;
+}
+
+static bool eeWrite(void *dst, const void *src, uint32_t len)
+{
+ return BL.blProgramEe(dst, src, len, BL_FLASH_KEY1, BL_FLASH_KEY2);
+}
+
+bool eeDataSet(uint32_t name, const void *buf, uint32_t len)
+{
+ uint32_t sz, effectiveSz, info = name + len * (EE_DATA_NAME_MAX + 1);
+ bool ret = true;
+ void *space;
+
+ if (!eeIsValidName(name))
+ return false;
+
+ //find the empty space at the end of everything and make sure it is really empty (size == EE_DATA_LEN_MAX)
+ space = eeFind(EE_DATA_NAME_MAX, 0, false, &sz);
+ if (!space || sz != EE_DATA_LEN_MAX)
+ return false;
+
+ //calculate effective size
+ effectiveSz = (len + 3) &~ 3;
+
+ //verify we have the space
+ if ((uint8_t*)__eedata_end - (uint8_t*)space < effectiveSz)
+ return false;
+
+ //write it in
+ ret = eeWrite(((uint32_t*)space) - 1, &info, sizeof(info)) && ret;
+ ret = eeWrite(space, buf, len) && ret;
+
+ return ret;
+}
+
+bool eeDataEraseOldVersion(uint32_t name, void *state)
+{
+ uint32_t v = *(uint32_t*)state;
+
+ if (!eeIsValidName(name))
+ return false;
+
+ //verify name
+ if ((v & EE_DATA_NAME_MAX) != name)
+ return false;
+
+ //clear name
+ v &=~ EE_DATA_NAME_MAX;
+
+ //store result
+ return eeWrite(state, &v, sizeof(v));
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/firmware/src/seos.c b/firmware/src/seos.c
index 95e7fdc..4f6bfda 100644
--- a/firmware/src/seos.c
+++ b/firmware/src/seos.c
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <plat/inc/eeData.h>
#include <plat/inc/plat.h>
#include <plat/inc/bl.h>
#include <platform.h>