Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Bootstrap ta #1928

Merged
merged 12 commits into from
Dec 7, 2017
Merged

[RFC] Bootstrap ta #1928

merged 12 commits into from
Dec 7, 2017

Conversation

jenswi-linaro
Copy link
Contributor

This pull request introduces bootstrap TAs which can completely replace the current TAs depending on how we'd like to progress.

I see some ways forward:

  1. Add this as yet another method of loading TAs
  2. Replace the current way of loading TAs from supplicant with this
  3. Wait until we have some security domain in place before starting to retire/deprecate 1

Doing 2 (or 3) doesn't mean that we have to remove the old code, we could just make it optional. But we'd change our current test setup to only install TAs via bootstrap TAs (or via a security domain).

Bootstrap TA are basically only the solution to the chicken and egg problem for security domains. Next step would be to introduce a security domain.

@jenswi-linaro
Copy link
Contributor Author

Uses OP-TEE/optee_test#240 to install bootstrap TAs

Note that the 9000 tests will fail if bootstrap TAs are installed.

@lorc
Copy link
Contributor

lorc commented Nov 9, 2017

Hi @jenswi-linaro, just a quick question: what do you mean when you say "security domain"?

@jenswi-linaro
Copy link
Contributor Author

Hi @lorc, this for instance: https://tools.ietf.org/html/draft-pei-opentrustprotocol-04#section-5.3

Note that Security Domains doesn't to have provide isolation between TAs in different Security Domains. A Security Domain is just a TA management domain.

@@ -0,0 +1,77 @@
#!/usr/bin/env python
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tested this script in both python2 and python3?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have now, and it seems to work. :-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay then :-)

@@ -0,0 +1,77 @@
#!/usr/bin/env python
#
# Copyright (c) 2015, Linaro Limited
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2017, I think :)

#

def uuid_parse(s):
from uuid import UUID
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check this script with pycodestyle (or with pip8.py). There will be a lot of warnings.

core/tee/tadb.c Outdated

if (db->files)
return TEE_SUCCESS;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove extra empty line.

core/tee/tadb.c Outdated

assert(db->refc);
db->refc--;
if (db->refc)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How you can guarantee thread safety in tadb manipulation?

Copy link
Contributor Author

@jenswi-linaro jenswi-linaro Nov 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions are supposed to be called from a static TA which will guarantee thread safety.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized that these functions are used from core/arch/arm/kernel/tadb_store.c which is outside the pseudo TA context. Ideally I should have a read/write lock to allow concurrent loading of TAs.

core/tee/tadb.c Outdated
tadb_put(db);
}

static TEE_Result populate_files(struct tee_tadb_dir *db)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Purpose of this function is bit unclear to me...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I thought this function was going to be used by several functions when doing the initial design. Now it's clear it's only needed in tee_tadb_ta_create(). I'll move the implementation into tee_tadb_ta_create() instead.

core/tee/tadb.c Outdated
size_t idx;
const TEE_UUID null_uuid = { 0 };

if (db->files)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There you return if db->files != NULL...

core/tee/tadb.c Outdated
if (!memcmp(&entry.prop.uuid, &null_uuid, sizeof(null_uuid)))
continue;

if (test_file(db, entry.file_number)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... and there you use db->files to check if file_number is stored. But at L265 you ensured that db->files is NULL.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is called in a loop, db->files could have been allocated at this point. test_file() and set_file() deals with that.

core/tee/tadb.c Outdated
int i = 0;

if (!ta)
res = TEE_ERROR_OUT_OF_MEMORY;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you missed return there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

core/tee/tadb.c Outdated
size_t num_bytes = 0;

while (num_bytes < l) {
uint8_t b[1024 * 4];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you really sure, you want to allocate 4kb on stack?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, it's a bit excessive. I'll replace it with malloc().

res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo),
&hash_size);
if (res != TEE_SUCCESS)
return res;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return TEE_ERROR_SECURITY?


res = crypto_ops.acipher.alloc_rsa_public_key(&key, shdr->sig_size);
if (res != TEE_SUCCESS)
return res;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return TEE_ERROR_SECURITY?

sizeof(*shdr));
if (res)
goto err_free_hash_ctx;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove extra empty line.

@jenswi-linaro jenswi-linaro mentioned this pull request Nov 14, 2017
@jenswi-linaro
Copy link
Contributor Author

Addressed comments, except then one with mutex (waiting for the outcome of #1942)

core/tee/tadb.c Outdated
continue;

if (test_file(db, entry.file_number)) {
DMSG("Clearing duplicate file number %" PRIu32,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that is not going to happen, then EMSG or at least IMSG will fit much better.


res = read_ent(db, idx, &entry);
if (res) {
if (res == TEE_ERROR_ITEM_NOT_FOUND)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is confusing, that only one successful (apart from L336) return from this function resides in the middle of it.
Now, when I grasped idea of this function, this seems obvious. But it was hard to understand from a first try.

This is just a note. I don't ask you to perform any actions.

core/tee/tadb.c Outdated
@@ -670,17 +694,25 @@ TEE_Result tee_tadb_ta_read(struct tee_tadb_ta *ta, void *buf, size_t *len)
return res;
} else {
size_t num_bytes = 0;
size_t b_size = MIN(SIZE_4K, l - num_bytes);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You zero out num_bytes at the line above. Better to leave only MIN(SIZE_4k, l). It is easier to read.

@@ -0,0 +1,77 @@
#!/usr/bin/env python
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay then :-)

*/
const struct tee_file_operations *tee_svc_storage_file_ops(uint32_t storage_id);


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: extra empty line.

@@ -71,5 +72,10 @@ struct shdr {
#define SHDR_GET_HASH(x) (uint8_t *)(((struct shdr *)(x)) + 1)
#define SHDR_GET_SIG(x) (SHDR_GET_HASH(x) + (x)->hash_size)

struct shdr_bootstrap_ta {
uint8_t uuid[16];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: uuid[sizeof(TEE_UUID)] ?


struct tee_tadb_ta;

struct tee_tadb_property {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a comment to describe the structure fields.

static void secstor_ta_close(struct user_ta_store_handle *h)
{
struct tee_tadb_ta *ta = (struct tee_tadb_ta *)h;
tee_tadb_ta_close(ta);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: add an empty line.

@jenswi-linaro
Copy link
Contributor Author

Rebased and squashed on top of master to be able to use the read lock. It turned out atomic reference counting routines where needed too, added that to the beginning of the PR.

Copy link
Contributor

@etienne-lms etienne-lms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few comments on the refcount part.
looking at the ta mngt services...

unsigned int val;
};

/* Increases refcount by 1, return true if val != 0 else false */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand the Api. I read this as "Return true if incremented refcount is not 0.", in which caserefcount_inc() must be changed. If not, maybe clarify the Api.

Same kind of comments on refcount_dec().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. I'll update the description.

unsigned int oval = atomic_load_uint(&r->val);

while (true) {
nval = oval + 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should read back in oval an updated value of recount val.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's actually taken care of by atomic_cas_uint()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, right, sorry.

core/tee/tadb.c Outdated
* grow the bitfield as needed.
*
* At the same time clean out duplicate file numbers, the first
* entry with the file number has precedence. Duplicate entries is
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: double space beforeDuplicate and before supposed at next line.

#include <tee/tee_svc_storage.h>
#include <utee_defines.h>

#define TADB_MAX_BUFFER_SIZE (64U * 1024)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does this comes from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do need some value, 64KiB is nothing for normal world to allocate as shared memory.

core/tee/tadb.c Outdated
#define TADB_TAG_SIZE TEE_AES_BLOCK_SIZE
#define TADB_KEY_SIZE TEE_AES_MAX_KEY_SIZE

struct user_ta_store_handle;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: unused

* TA binary
* @bin_size: Size of the binary TA
* @is_ta: True if this is a TA
* @is_root: True if this is a root SD or a TA without an SD
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/an/a/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It depends on how you pronounce it, I pronounce it ess-dee

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok :)

unsigned int oval = atomic_load_uint(&r->val);

while (true) {
nval = oval + 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, right, sorry.

*/
struct tee_tadb_property {
TEE_UUID uuid;
TEE_UUID parent;/* parent security domain, zeroes if nonexistent */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: tab before comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't fit on the line then. I'll remove it now that there's a description of the struct above.

@etienne-lms
Copy link
Contributor

minor: could you rename the pTA "management" into sometihng like "TA management"? For example management.c being a bit too generic, even in pta/ subdir. Something like ta_management.c?

@jenswi-linaro
Copy link
Contributor Author

Update

@jforissier
Copy link
Contributor

In order to give an opinion on this RFC, I need to understand the big picture. How does it work (high-level)? What problem are you trying to address? What is different from what we are currently doing? What is a bootstrap TA? Why does it have a different extension as mentioned in the optee_test PR (*.bsta)? How do you generate a .bsta? Is a different signing key required? Are bootstrap TAs still stored in the REE FS? You're mentioning security domains and how this could be a solution to the chicken-and-egg problem SDs have. How?

Sorry I don't feel like trying to figure this out from code only :(

@jenswi-linaro
Copy link
Contributor Author

Copy link
Contributor

@jforissier jforissier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my comments but overall I like this proposal.
The documentation will need updating, too (optee_design.md, section "12. Trusted Applications", and BTW this section also lacks some description of the "early TA" feature I merged some time ago...)

offs += sizeof(bs_ta);

memset(&property, 0, sizeof(property));
COMPILE_TIME_ASSERT(sizeof(property.uuid) == sizeof(property.uuid));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sizeof(bs_ta.uuid)


$(link-out-dir)/$(binary).bsta: $(link-out-dir)/$(binary).stripped.elf \
$(TA_SIGN_KEY)
@echo ' SIGN $@'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@$(cmd-echo-silent) (and fix above)

$(link-out-dir)/$(binary).bsta: $(link-out-dir)/$(binary).stripped.elf \
$(TA_SIGN_KEY)
@echo ' SIGN $@'
$(q)$(SIGN_BSTA) --key $(TA_SIGN_KEY) --uuid $(binary) --version 0 \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/TA_SIGN_KEY/BSTA_SIGN_KEY/? (default BSTA_SIGN_KEY ?= $(TA_SIGN_KEY))

TA_SIGN_KEY ?= $(TA_DEV_KIT_DIR)/keys/default_ta.pem

all: $(link-out-dir)/$(binary).elf $(link-out-dir)/$(binary).dmp \
$(link-out-dir)/$(binary).stripped.elf $(link-out-dir)/$(binary).ta
$(link-out-dir)/$(binary).stripped.elf $(link-out-dir)/$(binary).ta \
$(link-out-dir)/$(binary).bsta
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want to always generate a .bsta? Of course it is convenient for testing, but normally only one format will be used. So we should make this optional. For instance, only if $(BOOTSTRAP_TA)=y. This variable would be set or not by the Makefile for each TA. And, it could also be set globally for instance when building xtest (make BOOSTRAP_TA=y). Update: following your email and your proposal to have only one TA header (the new bsta one), the last part of this comment is not really relevant. I agree one header format would be more convenient.

@@ -2,6 +2,9 @@ ifeq ($(CFG_WITH_USER_TA),y)
srcs-y += user_ta.c
srcs-$(CFG_REE_FS_TA) += ree_fs_ta.c
srcs-$(CFG_EARLY_TA) += early_ta.c

$(call force,CFG_SECURE_STORAGE_TA,y,required by CFG_MANAGEMENT_PTA)
srcs-$(CFG_SECURE_STORAGE_TA) += tadb_store.c
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency with ree_fs_ta.c and early_ta.c, tadb_store.c, how about secure_storage_ta.c?

* When val becomes 0 refcount_inc() refuses to change the value any longer
* and returns false.
*
* refcount_dec() returns true becuase this call caused the value to become
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sp
May also be good to say that the function decrements the vallue: "refcount_dec() decrements the value and returns true when the call caused the value to become 0, false otherwise", or something like that.

while (true) {
nval = oval + 1;

/* r->val is 0, we can't doing anything more. */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/doing/do/


/* Increases refcount by 1, return true if val > 0 else false */
bool refcount_inc(struct refcount *r);
/* Decreases refcount by 1, return true if val > 0 else false */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return true if val == 0

* Reference conter
*
* When val becomes 0 refcount_inc() refuses to change the value any longer
* and returns false.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the wording a bit weird, a more neutral tone may be better: "When val is 0, refcount_inc() does not change the value and returns false.". You may add "Otherwise, it increments the value and returns true".

core/tee/sub.mk Outdated
@@ -40,6 +40,9 @@ srcs-y += tee_obj.c
srcs-y += tee_pobj.c
srcs-y += tee_time_generic.c

$(call force,CFG_SECURE_STORAGE_TA,y,required by CFG_MANAGEMENT_PTA)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed here

@jenswi-linaro jenswi-linaro force-pushed the bootstrap_ta branch 2 times, most recently from deecfc3 to 87b4bff Compare November 28, 2017 16:06
@jenswi-linaro
Copy link
Contributor Author

Squashed and inserted some extra commit but not rebased to make it easier to compare with the old a2aa4a0 state.

History is reordered to instead of adding a new sign script, the old one is replaced/updated and there's no .bsta file any longer. The REE FS TA storage now supports the new TA format as well as the old format.

I missed addressing the refcount comments, will make an update commit later. Documentation will also follow later.

@jenswi-linaro
Copy link
Contributor Author

Fixes problem with old filenumbers not being reused.

@jenswi-linaro
Copy link
Contributor Author

Addresses the refcount comments

@jenswi-linaro jenswi-linaro mentioned this pull request Nov 29, 2017
@jenswi-linaro
Copy link
Contributor Author

Added documentation in #1986

core/tee/tadb.c Outdated
size_t rl = len;
struct tee_fs_rpc_operation op;

assert(tadb_check_state(ta, TEE_MODE_ENCRYPT));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should return an error instead, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an API usage error (programmers error). In the case of tee_tadb_ta_write(), tee_tadb_ta_read() and tee_tadb_ta_close_and_commit() it's possible to return an error, but the two functions tee_tadb_ta_close_and_delete(), tee_tadb_ta_close() are void functions.

In all of the cases there's no good cleanup action that the caller can perform.There's obviously some confusion regarding what the handle is to be used for. Initially I was using two different structs for the "read" class and "write" class of functions. Perhaps I should reintroduce that instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there's no cleanup possible, then indeed a return code is useless.

Initially I was using two different structs for the "read" class and "write" class of functions. Perhaps I should reintroduce that instead?

Yes, I think I would like it better.

core/tee/tadb.c Outdated

void tee_tadb_ta_close_and_delete(struct tee_tadb_ta *ta)
{
assert(tadb_check_state(ta, TEE_MODE_ENCRYPT));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

core/tee/tadb.c Outdated
size_t sz = sizeof(ta->entry.tag);
size_t idx;

assert(tadb_check_state(ta, TEE_MODE_ENCRYPT));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

core/tee/tadb.c Outdated
const size_t sz = ta->entry.prop.custom_size + ta->entry.prop.bin_size;
size_t l = MIN(*len, sz - ta->pos);

assert(tadb_check_state(ta, TEE_MODE_DECRYPT));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

core/tee/tadb.c Outdated

void tee_tadb_ta_close(struct tee_tadb_ta *ta)
{
assert(tadb_check_state(ta, TEE_MODE_DECRYPT));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

mk/config.mk Outdated
@@ -262,6 +262,12 @@ CFG_GP_SOCKETS ?= y
# invocation parameters referring to specific secure memories).
CFG_SECURE_DATA_PATH ?= n

# Enable storage for TAs in secure storage
CFG_SECSTOR_TA ?= y
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on CFG_REE_FS=y.

I find the comment slightly misleading, since the bulk of the TA is actually not in secure storage but directly stored in the REE FS. How about adding: "TA binaries are stored in the REE FS and are protected by metadata in secure storage." or something like that. Will make the dependancy on CFG_REE_FS=y obvious.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated comment is fine. About the dependency I meant:

CFG_SECSTOR_TA ?= $(CFG_REE_FS)
$(call cfg-depends-all,CFG_SECSTOR_TA,CFG_REE_FS)

from argparse import ArgumentParser

parser = ArgumentParser()
parser.add_argument('--uuid', required=True,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be optional (default: parse --in file name).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the other hand, the name of the TA file doesn't have to be an UUID. Sounds like complicated usage to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True

@@ -58,4 +58,5 @@ $(link-out-dir)/$(binary).stripped.elf: $(link-out-dir)/$(binary).elf
$(link-out-dir)/$(binary).ta: $(link-out-dir)/$(binary).stripped.elf \
$(TA_SIGN_KEY)
@echo ' SIGN $@'
$(q)$(SIGN) --key $(TA_SIGN_KEY) --in $< --out $@
$(q)$(SIGN) --key $(TA_SIGN_KEY) --uuid $(binary) --version 0 \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming --uuid is optional, the command could remain unchanged

@jforissier
Copy link
Contributor

How about s/bootstrap/secure storage/g? My reasoning is: bootstrapping another TA management method (OTrP, etc.) is only one way this "secure storage TA" feature may be used. It is also perfectly valid to install all TAs in secure storage. So it would be more neutral and more general to use "secure storage TA", shdr_secstor_ta, and so on.

uint32_t custom_size;
uint32_t bin_size;
bool is_ta;
bool is_root;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since parent, handler, is_ta and is_root are currently not used, I'd rather introduce them later. It is fine to mention in the commit log that this may be a first step towards supporting SDs, but it should not show in the code yet. The "secure storage TA" feature is useful on its own.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

@jenswi-linaro
Copy link
Contributor Author

I don't agree with s/bootstrap/secure storage/g. I don't expect this to be used for anything but bootstrapping in a product. Test usage is another story, there we'll bootstrap a lot :-)

I'm expecting this flow in a product:

  1. bootstrap the TA management with a bootstrap TA containing keys needed for step 2 or bootstrap TA negotiates new keys
  2. the initial bootstrap TA receives to domain management TA (in some format, probably not bootstrap at least) signed with the keys from step 1
  3. the bootstrap TA creates a root security domain and installs the received TA as management TA
  4. the bootstrap TA isn't used any longer now that there's a security domain up and running

As you see bootstrap signed TAs are only supposed to be used for just that, that they happen to be stored in secure storage has nothing to do with what they are. The main reason why a new format was needed is to be able to protect against downgrade attack of the bootstrap TA.

@jenswi-linaro
Copy link
Contributor Author

@lorc, sorry, addressed the comments now.

@jenswi-linaro
Copy link
Contributor Author

Squashed and rebased, for reference the old state was bef845d

@jenswi-linaro
Copy link
Contributor Author

Fixed checkpatch error

Copy link
Contributor

@jforissier jforissier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is xtest _9 failing in CI?

A few more comments here and there. Note that the SPDX/copyright stuff applies to a number of files. So, with my comments addressed:

/*
* Note that atomic_cas_uint() updates oval to the current
* r->val read, regardless of return value.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor:

I was a bit disturbed by this comment, because:

  1. We're only interested in what happens with oval when the function returns false.
  2. When the function returns true, oval already has the value of r->val, so it is not really updated anyway

I'd suggest: /* At this point atomic_cas_uint() has updated oval to the current r->val */ after the if().

Same below.

* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* SPDX-License-Identifier: BSD-2-Clause
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep the license text and add the SPDX ID before.

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2017, Linaro Limited
* All rights reserved.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"All rights reserved" is cargo cult and IMO should better be omitted in new files (Wikipedia).

return NULL;
memcpy(shdr, img, shdr_size);

/* Check that the data wasn't modified before the copy was completed */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this add any security? I fail to imagine a case where continuing would be a problem, since the TA is signed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If shdr->hash_size or shdr->sig_size is increased we may access data outside the allocated buffer later on.

scripts/sign.py Outdated
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# SPDX-License-Identifier: BSD-2-Clause
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep the license text

# TA binaries are stored encrypted in the REE FS and are protected by
# metadata in secure storage.
CFG_SECSTOR_TA ?= $(call cfg-all-enabled,CFG_REE_FS CFG_WITH_USER_TA)
$(eval $(call cfg-depends-all,CFG_SECSTOR_TA,CFG_REE_FS CFG_WITH_USER_TA))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two lines should go into commit "core: add ta storage based on tadb", not in "core: add management pseudo TA".

@jenswi-linaro
Copy link
Contributor Author

xtest _9 is failing because there's a secure storage object created for the TA database, this changes the names of the other secure storage objects. That's the main reason why I updated the htree tests a while ago, to be able to get rid of the xtest _9 tests.

@jenswi-linaro
Copy link
Contributor Author

Comments, addressed, squashed and tags applied.

@lorc
Copy link
Contributor

lorc commented Dec 1, 2017

Reviewed-by: Volodymyr Babchuk <[email protected]>

* Adds atomic_load_uint() and atomic_load_u32()
* Adds atomic_store_uint() and atomic_store_u32()
* Adds atomic_cas_uint() and atomic_cas_u32(), compare and store

Reviewed-by: Volodymyr Babchuk <[email protected]>
Reviewed-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
Adds refcount_inc() and refcount_dec()

Reviewed-by: Volodymyr Babchuk <[email protected]>
Reviewed-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
Fixes problem with creating an empty htree file.

Reviewed-by: Volodymyr Babchuk <[email protected]>
Acked-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
Reviewed-by: Volodymyr Babchuk <[email protected]>
Reviewed-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
Adds a signed header type for bootstrap TA. This type is used when there
isn't any security domains installed yet.

Reviewed-by: Volodymyr Babchuk <[email protected]>
Reviewed-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
Adds struct shdr helper functions to allocate and verify a struct shdr.

Reviewed-by: Volodymyr Babchuk <[email protected]>
Reviewed-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
Uses the new shdr_*() helper functions to verify a signed header.

Reviewed-by: Volodymyr Babchuk <[email protected]>
Reviewed-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
Adds support for the new bootstrap TA format to the REE FS TA storage.

Reviewed-by: Volodymyr Babchuk <[email protected]>
Reviewed-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
Changes to TA sign script to sign TAs as Bootstrap TAs
(img_type == SHDR_BOOTSTRAP_TA) instead of the legacy
TA format (img_type == SHDR_TA).

Reviewed-by: Volodymyr Babchuk <[email protected]>
Reviewed-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
Adds tadb which is a database in which TAs can be stored leveraging
secure storage for anti-rollback, key storage and list of TAs.

Reviewed-by: Volodymyr Babchuk <[email protected]>
Acked-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
Adds ta storage based on tadb. The TAs has to be installed in tadb
before they can be loaded.

Reviewed-by: Volodymyr Babchuk <[email protected]>
Reviewed-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
Adds a pseudo TA for management of Trusted Applications and Security
Domains. The pseudo TA only provides a minimal interface, a more
advanced interface is supposed to be provided by a user TA using this
pseudo TA. Such a TA could for instance implement Global Platforms TEE
Management Framework or OTrP.

The management TA currently only supports installing bootstrap packaged
TAs in secure storage.

Reviewed-by: Volodymyr Babchuk <[email protected]>
Reviewed-by: Jerome Forissier <[email protected]>
Tested-by: Jerome Forissier <[email protected]> (HiKey960)
Tested-by: Jens Wiklander <[email protected]> (QEMU)
Signed-off-by: Jens Wiklander <[email protected]>
@jenswi-linaro
Copy link
Contributor Author

Tag applied

@jenswi-linaro
Copy link
Contributor Author

What's next step here?

@jforissier
Copy link
Contributor

Since this breaks the xtest _9 series, I'd like to merge OP-TEE/optee_test#240 first.

@jforissier
Copy link
Contributor

All good now. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants