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 v4] Remote attestation PTA #5010

Closed
wants to merge 6 commits into from

Conversation

jforissier
Copy link
Contributor

Differences with v3:

  • The RSA signing key is generated by the PTA the first time it is called, then written to secure storage. Implements the suggestions by @etienne-lms and @b49020. A PTA command is added to obtain the public key.

The hashing method is unchanged: the PTA still returns the hash found in the TA header as in RFC v3. For simplicity I have chosen not to re-introduce the in-memory hashing found in RFC v1 and v2 which I think addresses a slightly different use case. It could easily be done if needed.

Add a Python script to dump the information contained in the header of
a TA file (*.ta). One use case is to extract struct shdr::hash, which is
returned by the attestation PTA to be added in a later commit.

Signed-off-by: Jerome Forissier <jerome@forissier.org>
…pc.c

tee_svc_storage_create_filename_dfh() is only used in
core/tee/tee_fs_rpc.c, so move it there and make it static.
Fundamentally, this function is needed when CFG_REE_FS=y but the whole
file core/tee/tee_svc_storage.c (which is the current location of this
function) essentially defines the storage syscalls for TAs and is
therefore not needed when CFG_WITH_USER_TA=n. If we want to later be
able to exclude it from the build while still providing secure storage
to kernel code, the function has to move.

Signed-off-by: Jerome Forissier <jerome@forissier.org>
core/tee/fs_htree.c is used when CFG_REE_FS=y, and is also used by the
test PTA core/pta/tests/fs_htree.c. Rather than make the implementation
depend on the test (CFG_TEE_CORE_EMBED_INTERNAL_TESTS), do the opposite.

Signed-off-by: Jerome Forissier <jerome@forissier.org>
Adds _CFG_WITH_SECURE_STORAGE set to 'y' when at least one secure
storage backend is enabled.

Signed-off-by: Jerome Forissier <jerome@forissier.org>
Some files which are currently guarded with CFG_WITH_USER_TA should be
guarded with _CFG_WITH_SECURE_STORAGE. This will allow the use of
secure storage from kernel code when CFG_WITH_USER_TA=n.

Signed-off-by: Jerome Forissier <jerome@forissier.org>
Add a PTA to perform remote attestation of user space TAs. Enabled with
CFG_ATTESTATION_PTA=y.

This feature allows a client application to request a measurement of any
Trusted Application or TA shared library installed on the device. The CA
generates a random nonce and sends it to the attestation Pseudo TA,
along with the UUID of the TA to be measured. The measurement is the TA
hash found in the TA header (struct shdr::hash). It is hashed once more
together with the nonce, then the resulting digest is signed using a
private key that is generated by the PTA upon the first invocation. The
key is persistent (written into secure storage). A command can be used
by the client to retrieve the public key; the private key never leaves
the TEE. This command would typically be invoked only during device
provisioning so that the key pair is generated and the public key is
returned in a trusted environment.

Signed-off-by: Jerome Forissier <jerome@forissier.org>
@b49020
Copy link
Contributor

b49020 commented Nov 30, 2021

@jforissier,

The hashing method is unchanged: the PTA still returns the hash found in the TA header as in RFC v3.

Can you elaborate the use-case where it would be beneficial? AFAICS, if we just return the hash found in the TA header then we can also return the verified signature found in the TA header. I am not sure what OP-TEE core is attesting in this case and why there is any need to add a new attestation key to suffice this purpose only.

@jforissier
Copy link
Contributor Author

@jforissier,

The hashing method is unchanged: the PTA still returns the hash found in the TA header as in RFC v3.

Can you elaborate the use-case where it would be beneficial? AFAICS, if we just return the hash found in the TA header then we can also return the verified signature found in the TA header. I am not sure what OP-TEE core is attesting in this case and why there is any need to add a new attestation key to suffice this purpose only.

With a per-device key and a new signature on each call we can authenticate the device as well as make sure the measurement is fresh. If the PTA were to return the TA signature, a malicious actor could intercept the communication before it reaches the PTA and return stale data.

Let's consider the definition of attestation found at https://graphene.readthedocs.io/en/latest/attestation.html: "Broadly speaking, attestation is a mechanism for a remote user to verify that the application runs on a real hardware in an up-to-date TEE with the expected initial state."

  • The per-device attestation key ensures the hardware is genuine (and is indeed the expected device)
  • The "up-to-date TEE" part is not covered :-/
  • The expected initial state is represented by the TA hash (in this version of the RFC), or by a hash of in-memory pages (RFC v1 or v2)
  • Since a new signature is generated each time the PTA is called, replay attacks are impossible

@b49020
Copy link
Contributor

b49020 commented Dec 1, 2021

Thanks @jforissier for insights into the use-case but now I am confused whether you are trying to attest the whole TEE or only a particular TA.

AFAIU, the current implementation ensures to remote entity that this PTA have access to attestation key without any assurance about if the PTA (or TEE as a whole) itself is genuine or compromised. IMO, "up-to-date TEE with the expected initial state" phrase is critical here.

The "up-to-date TEE" part is not covered :-/
The expected initial state is represented by the TA hash (in this version of the RFC), or by a hash of in-memory pages (RFC v1 or v2)

We need to provide signed hash for TEE's initial state as well. IMO, the hash of in-memory pages would be more robust for both TEE and TA.

@jforissier
Copy link
Contributor Author

Thanks @jforissier for insights into the use-case but now I am confused whether you are trying to attest the whole TEE or only a particular TA.

Only a particular TA at this point.

AFAIU, the current implementation ensures to remote entity that this PTA have access to attestation key without any assurance about if the PTA (or TEE as a whole) itself is genuine or compromised. IMO, "up-to-date TEE with the expected initial state" phrase is critical here.

Yes, I agree the integrity of the TEE is critical, and a prerequisite to trusting the attestation mechanism for the TAs.

The "up-to-date TEE" part is not covered :-/
The expected initial state is represented by the TA hash (in this version of the RFC), or by a hash of in-memory pages (RFC v1 or v2)

We need to provide signed hash for TEE's initial state as well.

Yes, that shouldn't be too difficult, I will think about it.

IMO, the hash of in-memory pages would be more robust for both TEE and TA.

I don't disagree ;-) although not a silver bullet either. For example, if an entity performs remote attestation for a TA that is able to load libraries dynamically, the moment when the measurement is made is very important since a library is part of the measurement only after it is loaded obviously.

There is a related discussion in a paper titled Establishing Mutually Trusted Channels for Remote Sensing
Devices with Trusted Execution Environments
, section 4.3. Attestation of the TA "at rest" (or at load time) still has some value.

@b49020
Copy link
Contributor

b49020 commented Dec 1, 2021

IMO, the hash of in-memory pages would be more robust for both TEE and TA.

I don't disagree ;-) although not a silver bullet either. For example, if an entity performs remote attestation for a TA that is able to load libraries dynamically, the moment when the measurement is made is very important since a library is part of the measurement only after it is loaded obviously.

The moment for measurement should be after a session to a TA is opened. AFAIK, all the dynamic libraries should be loaded as part of open session. And in case of TEE core measurement, it shouldn't be a problem.

There is a related discussion in a paper titled Establishing Mutually Trusted Channels for Remote Sensing
Devices with Trusted Execution Environments, section 4.3. Attestation of the TA "at rest" (or at load time) still has some value.

I am not sure if we can call the current TA measurement to be done "at load time" since we are just fetching TA from REE-FS, measuring it and then close reference without loading it into secure RAM.

And the other aspect being if the current TA measurement would provide any value for:

"... long-running TAs, like those collecting sensing data over long periods of time, which may run for days without being rebooted/reverified." mentioned in section 4.3.

@jforissier
Copy link
Contributor Author

The moment for measurement should be after a session to a TA is opened. AFAIK, all the dynamic libraries should be loaded as part of open session.

Most of the time yes, but not if the TA use the dlopen()/dlsym() API.

And in case of TEE core measurement, it shouldn't be a problem.

Right.

@b49020
Copy link
Contributor

b49020 commented Dec 1, 2021

The moment for measurement should be after a session to a TA is opened. AFAIK, all the dynamic libraries should be loaded as part of open session.

Most of the time yes, but not if the TA use the dlopen()/dlsym() API.

Although, I would generally prefer to load dynamic libraries via dlopen() API in TA_OpenSessionEntryPoint() and dlclose() in TA_CloseSessionEntryPoint(). But if the TA is a bit more complex and requires dynamic libraries to be loaded during invoke commands then IMO the remote attestation of that particular TA need to be compare against multiple good known TA hash values (w/ and w/o dynamic library) computed during provisioning.

Also, we can share UUIDs of TA and loaded libraries as measurement metadata.

@jforissier
Copy link
Contributor Author

We need to provide signed hash for TEE's initial state as well.

Yes, that shouldn't be too difficult, I will think about it.

Well, more difficult than I initially thought, because tee.elf has TEXTREL, so the hash will change based on the load address (with ASLR). If we could get rid of the relocations inside .text that would be great, but IIRC they are due to hand-written assembly which may not be easily written differently?

0xe101788 in .text <stack_tmp_export> RELA type R_AARCH64_RELATIVE sym 0 addend e197ab0 <stack_tmp + 2096>
0xe1018d0 in .text <thread_vector_table + 36> RELA type R_AARCH64_RELATIVE sym 0 addend e101798 <$x + 8>
0xe1018e0 in .text <thread_vector_table + 52> RELA type R_AARCH64_RELATIVE sym 0 addend e1017b4 <vector_fast_smc_entry + 8>
0xe1018e8 in .text <thread_vector_table + 60> RELA type R_AARCH64_RELATIVE sym 0 addend e1017f8 <vector_fiq_entry + 8>
0xe101900 in .text <thread_vector_table + 84> RELA type R_AARCH64_RELATIVE sym 0 addend e101828 <vector_cpu_off_entry + 8>
0xe101910 in .text <thread_vector_table + 100> RELA type R_AARCH64_RELATIVE sym 0 addend e101844 <vector_cpu_suspend_entry + 8>
0xe101920 in .text <thread_vector_table + 116> RELA type R_AARCH64_RELATIVE sym 0 addend e101860 <vector_cpu_resume_entry + 8>
0xe101930 in .text <thread_vector_table + 132> RELA type R_AARCH64_RELATIVE sym 0 addend e10187c <vector_system_off_entry + 8>
0xe101940 in .text <thread_vector_table + 148> RELA type R_AARCH64_RELATIVE sym 0 addend e101898 <vector_system_reset_entry + 8>
0xe103088 in .text <icache_inv_user_range + 152> RELA type R_AARCH64_RELATIVE sym 0 addend e102424 <el0_sync_a64 + 36>
0xe103090 in .text <icache_inv_user_range + 160> RELA type R_AARCH64_RELATIVE sym 0 addend e1024a4 <el0_irq_a64 + 36>
0xe103098 in .text <icache_inv_user_range + 168> RELA type R_AARCH64_RELATIVE sym 0 addend e102524 <el0_fiq_a64 + 36>
0xe1030a0 in .text <icache_inv_user_range + 176> RELA type R_AARCH64_RELATIVE sym 0 addend e102624 <el0_sync_a32 + 36>
0xe1030a8 in .text <icache_inv_user_range + 184> RELA type R_AARCH64_RELATIVE sym 0 addend e1026a4 <el0_irq_a32 + 36>
0xe1030b0 in .text <icache_inv_user_range + 192> RELA type R_AARCH64_RELATIVE sym 0 addend e102724 <el0_fiq_a32 + 36>
0xe1030b8 in .text <icache_inv_user_range + 200> RELA type R_AARCH64_RELATIVE sym 0 addend e102fbc <eret_to_el0 + 56>
0xe1030c0 in .text <icache_inv_user_range + 208> RELA type R_AARCH64_RELATIVE sym 0 addend e103020 <icache_inv_user_range + 48>
0xe1030c8 in .text <icache_inv_user_range + 216> RELA type R_AARCH64_RELATIVE sym 0 addend e103074 <icache_inv_user_range + 132>
0xe1035a0 in .text <__thread_enter_user_mode + 160> RELA type R_AARCH64_RELATIVE sym 0 addend e164b80 <threads>
0xe1036b0 in .text <$x + 264> RELA type R_AARCH64_RELATIVE sym 0 addend e164b80 <threads>
0xe103778 in .text <$x + 192> RELA type R_AARCH64_RELATIVE sym 0 addend e164b80 <threads>

@ruchi393
Copy link
Contributor

ruchi393 commented Dec 2, 2021

We need to provide signed hash for TEE's initial state as well.

Yes, that shouldn't be too difficult, I will think about it.

Well, more difficult than I initially thought, because tee.elf has TEXTREL, so the hash will change based on the load address (with ASLR). If we could get rid of the relocations inside .text that would be great, but IIRC they are due to hand-written assembly which may not be easily written differently?

0xe101788 in .text <stack_tmp_export> RELA type R_AARCH64_RELATIVE sym 0 addend e197ab0 <stack_tmp + 2096>
0xe1018d0 in .text <thread_vector_table + 36> RELA type R_AARCH64_RELATIVE sym 0 addend e101798 <$x + 8>
0xe1018e0 in .text <thread_vector_table + 52> RELA type R_AARCH64_RELATIVE sym 0 addend e1017b4 <vector_fast_smc_entry + 8>
0xe1018e8 in .text <thread_vector_table + 60> RELA type R_AARCH64_RELATIVE sym 0 addend e1017f8 <vector_fiq_entry + 8>
0xe101900 in .text <thread_vector_table + 84> RELA type R_AARCH64_RELATIVE sym 0 addend e101828 <vector_cpu_off_entry + 8>
0xe101910 in .text <thread_vector_table + 100> RELA type R_AARCH64_RELATIVE sym 0 addend e101844 <vector_cpu_suspend_entry + 8>
0xe101920 in .text <thread_vector_table + 116> RELA type R_AARCH64_RELATIVE sym 0 addend e101860 <vector_cpu_resume_entry + 8>
0xe101930 in .text <thread_vector_table + 132> RELA type R_AARCH64_RELATIVE sym 0 addend e10187c <vector_system_off_entry + 8>
0xe101940 in .text <thread_vector_table + 148> RELA type R_AARCH64_RELATIVE sym 0 addend e101898 <vector_system_reset_entry + 8>
0xe103088 in .text <icache_inv_user_range + 152> RELA type R_AARCH64_RELATIVE sym 0 addend e102424 <el0_sync_a64 + 36>
0xe103090 in .text <icache_inv_user_range + 160> RELA type R_AARCH64_RELATIVE sym 0 addend e1024a4 <el0_irq_a64 + 36>
0xe103098 in .text <icache_inv_user_range + 168> RELA type R_AARCH64_RELATIVE sym 0 addend e102524 <el0_fiq_a64 + 36>
0xe1030a0 in .text <icache_inv_user_range + 176> RELA type R_AARCH64_RELATIVE sym 0 addend e102624 <el0_sync_a32 + 36>
0xe1030a8 in .text <icache_inv_user_range + 184> RELA type R_AARCH64_RELATIVE sym 0 addend e1026a4 <el0_irq_a32 + 36>
0xe1030b0 in .text <icache_inv_user_range + 192> RELA type R_AARCH64_RELATIVE sym 0 addend e102724 <el0_fiq_a32 + 36>
0xe1030b8 in .text <icache_inv_user_range + 200> RELA type R_AARCH64_RELATIVE sym 0 addend e102fbc <eret_to_el0 + 56>
0xe1030c0 in .text <icache_inv_user_range + 208> RELA type R_AARCH64_RELATIVE sym 0 addend e103020 <icache_inv_user_range + 48>
0xe1030c8 in .text <icache_inv_user_range + 216> RELA type R_AARCH64_RELATIVE sym 0 addend e103074 <icache_inv_user_range + 132>
0xe1035a0 in .text <__thread_enter_user_mode + 160> RELA type R_AARCH64_RELATIVE sym 0 addend e164b80 <threads>
0xe1036b0 in .text <$x + 264> RELA type R_AARCH64_RELATIVE sym 0 addend e164b80 <threads>
0xe103778 in .text <$x + 192> RELA type R_AARCH64_RELATIVE sym 0 addend e164b80 <threads>

can we use the measurements passed by the firmware which loads TEE here ? Right now TF-A passes the measurements in form of TPM based TCG specific eventlog but it should be easy to construct some mechanism by which the firmware which loads the TEE can pass it's own measurement and TEE's measurement securely to TEE which can be then added in this quote being constructed.

TEE_Result res = TEE_SUCCESS;

if (!key) {
res = load_key();
Copy link
Contributor

Choose a reason for hiding this comment

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

Should a provision be added to provide an option to get a key here in platform defined way. So platforms can choose to generate the key internally and export the public key our or have the ability to import their own attestation key protected by some platform specific key.
For eg, I remember in #4011
they talked about having

  • platform specific key (called endorsement key)
  • Attestation data [ which had the encrypted private attestation key in it]
    The attestation key was obtained after decrypting this attestation data.

TPM attestation also talks about different ways of provisioning attestation keys. https://tpm2-software.github.io/tpm2-tss/getting-started/2019/12/18/Remote-Attestation.html

So having a provision here to allow platform to get their own key somehow during provisioning process may be useful.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, some flexibility can easily be added for instance with weak functions. I'd rather wait until a use case is clarified so that we can define a suitable interface.

return res;
return sign_digest(out + TEE_SHA256_HASH_SIZE,
out_sz - TEE_SHA256_HASH_SIZE, digest);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

IIUC there are usually 3 steps in attestation

  1. Provisioning the attestation key -> one time step -> the key can be generated as proposed here or can be imported in platform specific way
  2. generating a quote
  3. Signing the quote

Should there be some provision to

  • add system measurements in the quote (TF-A today passes measurements in fom of TPM understandable eventlog to TEE, platforms can choose to use that or some other way of getting these measurements). These measurements passed by TF-A would include TEE measurements also as it is the one which loads the TEE
  • provide a function to get ta hash and let generation of quote be a weak function where we show a possible way to generate this quote and leave an option for platform to construct their own quote with received nonce.

@b49020
Copy link
Contributor

b49020 commented Dec 2, 2021

Hi @ruchi393,

can we use the measurements passed by the firmware which loads TEE here ? Right now TF-A passes the measurements in form of TPM based TCG specific eventlog but it should be easy to construct some mechanism by which the firmware which loads the TEE can pass it's own measurement and TEE's measurement securely to TEE which can be then added in this quote being constructed.

I think there are basic differences in how we are trying to propose a remote attestation of Trusted Applications. Let me try to elaborate here.

There are basically two categories for root of trust for measurement, following are definition quotes from this paper:

  1. Static root of trust for measurement (SRTM) by as defined by the TCG, a fixed or
    immutable piece of trusted code in the BIOS is loaded at the start of the entire booting chain, and
    every piece of code in the chain is measured by the predecessor code before it is executed. Thus any
    compromised code in the chain cannot escape from being measured and therefore from being
    detected. The SRTM however has obvious scalability shortcomings if we intend to measure every
    component in the trust chain; in addition, it gives only the load time guarantee but not the run time
    guarantee for the launched environment.
  2. Dynamic root of trust for measurement (DRTM) is the underlying trust mechanism for Intel’s
    Trusted Execution Technology (TXT) and AMD’s Secure Virtual Machine (SVM) technology. It
    introduces platform level enhancements in order to provide run time protection and guarantee. In
    contrast with the SRTM, the DRTM has the advantage that the launch of the measured environment
    can occur at any time without resorting to a platform reset.

AFAIU from @jforissier current implementation and references to https://graphene.readthedocs.io/en/latest/attestation.html, it is the DRTM we are targeting currently. @jforissier, feel free to correct me if I am missing something.

So for DRTM, we need to provide signed runtime or load time hashes of the entity that we are trying to attest. In our case its the TA but to attest it we need to prove that the attesting entity (TEE core) is genuine or not. That would require signed runtime or load time hash of attesting entity as well.

@ruchi393
Copy link
Contributor

ruchi393 commented Dec 2, 2021

Hi @ruchi393,

can we use the measurements passed by the firmware which loads TEE here ? Right now TF-A passes the measurements in form of TPM based TCG specific eventlog but it should be easy to construct some mechanism by which the firmware which loads the TEE can pass it's own measurement and TEE's measurement securely to TEE which can be then added in this quote being constructed.

I think there is basic differences in how we are trying to propose a remote attestation of Trusted Applications. Let me try to elaborate here.

There are basically two categories for root of trust for measurement, following definition quotes from this paper:

  1. Static root of trust for measurement (SRTM) by as defined by the TCG, a fixed or
    immutable piece of trusted code in the BIOS is loaded at the start of the entire booting chain, and
    every piece of code in the chain is measured by the predecessor code before it is executed. Thus any
    compromised code in the chain cannot escape from being measured and therefore from being
    detected. The SRTM however has obvious scalability shortcomings if we intend to measure every
    component in the trust chain; in addition, it gives only the load time guarantee but not the run time
    guarantee for the launched environment.
  2. Dynamic root of trust for measurement (DRTM) is the underlying trust mechanism for Intel’s
    Trusted Execution Technology (TXT) and AMD’s Secure Virtual Machine (SVM) technology. It
    introduces platform level enhancements in order to provide run time protection and guarantee. In
    contrast with the SRTM, the DRTM has the advantage that the launch of the measured environment
    can occur at any time without resorting to a platform reset.

AFAIU from @jforissier current implementation and references to https://graphene.readthedocs.io/en/latest/attestation.html, it is the DRTM we are targeting currently. @jforissier, feel free to correct me if I am missing something.

So for DRTM, we need to provide signed runtime or load time hashes of the entity that we are trying to attest. In our case its the TA but to attest it we need to prove that the attesting entity (TEE core) is genuine or not. That would require signed runtime or load time hash of attesting entity as well.

Sorry, but I am not sure if I understand how SRTM and DRTM are related with content of the quote. IIUC, there has to be an agreement between attester and verifier on what the content of the quote would be. Quote should help prove that attesting entity and the hardware it is running on is genuine. If we are considering load time hash here, the loader of TEE is TF-A, so we may use the hash passed by TF-A/loading entity. ( I am not saying we have to use the TPM eventlog, it can be in much simpler format. Basically have a provision where firmware which loads the TEE also passes it's hash to TEE)

@b49020
Copy link
Contributor

b49020 commented Dec 2, 2021

Sorry, but I am not sure if I understand how SRTM and DRTM are related with content of the quote.

AFAIK, the basic difference with respect to quote contents is whether its made up of hashes which are measured as an aggregated hash once during boot time (SRTM) or measured at runtime when requested (DRTM).

If we are considering load time hash here, the loader of TEE is TF-A, so we may use the hash passed by TF-A/loading entity.

I guess there is some confusion as I have used load time. By load time I just meant measurement of TAs during loading. But the overall idea behind DRTM is that the measurement should be fresh. IOW, TAs should be measured when requested. And same hold true for TEE as well.

@jforissier
Copy link
Contributor Author

@ruchi393 @b49020 thanks for the comments so far. I agree that providing a runtime measurement is more valuable than a boot time one, so I plan to re-introduce the TA page hashing from v2.
However, I will also keep the code that returns the digest found in the TA header because I believe there are some valid uses cases for it (it allows to easily identify which versions of TAs are deployed on a device, the digest can conveniently be extracted from the .ta file itself outside the TEE environment).
Finally, I will introduce a new command to hash the TEE binary at runtime, subject to CFG_CORE_ASLR=n for the time being, at least until we can find a way to either eliminate the TEXTREL or work around it. I am not sure it can provides strong guarantees since the attestation PTA is part of the TEE core, so if the TEE is compromised the PTA cannot really be trusted. Still better than nothing perhaps?

@b49020
Copy link
Contributor

b49020 commented Dec 2, 2021

I am not sure it can provides strong guarantees since the attestation PTA is part of the TEE core, so if the TEE is compromised the PTA cannot really be trusted. Still better than nothing perhaps?

Agree, if we talk in terms of PTA (part of TEE) compromises then that may cause attestation key to be leaked as well which can lead to MITM attacks. But IMO, adding runtime TEE measurement is still worthwhile thing at-least to reduce attack surface.

@b49020
Copy link
Contributor

b49020 commented Dec 2, 2021

@jforissier I think it would also be better to document all these remote attestation design considerations for future reference.

@github-actions
Copy link

github-actions bot commented Jan 2, 2022

This pull request has been marked as a stale pull request because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this pull request will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.

@github-actions github-actions bot added the Stale label Jan 2, 2022
@github-actions github-actions bot closed this Jan 7, 2022
@jforissier jforissier deleted the attestation-4 branch September 30, 2022 06:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants