lawik

lawik

Nerves Core Team

Another one where me and @fhunleth have gone kind of deep on a topic and I figure this information should be in the community. Findable.

So NervesKey is a cool library for setting up device certificates and via nerves_key_pkcs11 it allows us to override what OpenSSL uses for particular connections and suddenly we can have a high degree of certainty about which device is connecting. This works for NervesHub and other IoT cloud things. TLS with device certificates without unduly findable provate keys is fantastic.

This uses the Microchip ATECC508/ATECC608A/ATECC608B series. Interestingly the 608 chips can also hide secrets for symmetric encryption. Sweet. Suddenly a world opens. Hide your SQLite encryption key, you disk encryption key, key to your journal.

Not quite. Signatures are not secret, authenticity is “easier” than secrecy. In the midst of my excitement Frank noted that the darned thing ships decrypted secreta over a slow, plain I2C bus. So it is physically exposed at the time of decryption, travelling to the SoC.

I have been digging for options for my client REDACTED. We can probably physically secure the unit with tamper protection to mitigate the I2C bus being exposed but a deeper protection would be nice.

Beyond the plaintext transport the ATECC chips have been hit with some novel laser fault injection hacks, that while risky and kind of demanding, have potentially real implications to the security of the device.

Currently I’ve seen NXP EdgeLock, either in the iMX9-series, iMX8ULP devices or standalone via SE050 chip. I am sure there are others I am not aware of, these bill themselves as a Secure Enclave.

The other interesting angle is ARM TrustZone plus OP-TEE which lets parts of an SoC run trusted code only and allows the designer to include certain hardware only in the trusted part. This enables heavier security in terms of hiding secrets.

All of these approaches should typically allow interop with OpenSSL to get stuff done.

I would love to push this forward as my work progresses specifically for Nerves and I am curious if others have done it or have hardware recommendations.

Showing Posts 1 to 9

lawik

lawik OP

Nerves Core Team

I am travelling now but at home I apparently have a bundle of these waiting for me. The NXP EdgeLock TM SE050. Will see if I get a chance to do something with it.

lawik

lawik OP

Nerves Core Team

SE050 datasheet

“Support for SCP03 protocol (bus encryption and encrypted credential injection) to securely bind the host with
the secure element”
more on SCP03

Finding details for this? Probably in an “Application note” somewhere :smiley:

gus

gus

Nerves Core Team

It looks like NXP published an app note about how to bind a host to the device here.

Section 2.1 has a link to the SCP protocol spec sheet, which seems to want to collect your email before you can view it.

This is a very dense data sheet and I’m pretty sure you’re aware, but I want to point out two of the functions/operating modes because it wasn’t immediately clear to me: It has 50kb secure onboard storage for encryption keys and such, so it would be a secure replacement to the ATECC line of chips used by Nerves Key.

But also has a secondary function (which was my first impression of the chip does when I read the data sheet) to add a semi-secure bridge between a controller and a sensor or storage chip. You could theoretically store your keys in the ATECC chips, and use the SE050 to create an encrypted channel of communication, but which is still plaintext on the ATECC side of things. This doesn’t really get you anywhere in terms of security, as you’d still have plaintext keys on an I2C bus (just not one that is talking with the host device), plus the other security considerations of the ATECC chips you mentioned above.

The only reason I can think of for why they have this functionality is for hosts with just one I2C controller to be able have encrypted bus communications while still supporting reads and writes of traditional I2C sensors which don’t need encryption.

In terms of implementation, I’d be willing to bet there is a NXP provided implementation which might be possible to repackage into a NIF. More fun in Elixir land though :smiley:

If you make any progress on supporting the chip please post updates, I’m curious to follow along!

lawik

lawik OP

Nerves Core Team

Will dig into that when I get a moment :slight_smile:

Yeah, so it seems like it would cover all the ground the ATECC chips cover but also seems to have a way to encrypt the transport. It also has a lot of other features that may or may not be necessary. From what I can tell the ATECC is essentially unnecessary with this.

Their SDK stuff includes a PKCS11 module so you can hook it into OpenSSL directly.

And while I’d prefer to implement support for it from Elixir, as you say, there is an implementation. The fast path is probably to lean on their implementation initially.

I’m quite curious about the support for NFC-ish powering and provisioning. Being able to provision/program devices by blooping a device to them seems wild. Not important to what I’m currently up to but interesting.

I didn’t dig into that extra I2C functionality, also not clear how running a sensor in plaintext via a secure chip is any more secure than running it directly :slight_smile:

Right now I’m travelling and these samples just arrived at home. Near term I don’t have license (read someone paying me) to run a lab on them. Will report more when I do :slight_smile:

lawik

lawik OP

Nerves Core Team

I have kept digging into this for the ATECC chip as well with just the goal of being able to get a secret for full disk encryption that could only be provided from the secure element and with reasonable protection on the bus. This thread seems to have an answer. You use the HKDF mechanism (well the part I think) and it can take something in a private/protected slot on the chip, take an input and produce an output.

I have a very rough hacking session going on this for ATECC508A.Request:

@atecc508a_op_kdf 0x56
  def kdf(transport, input, a \\ 0x00) do
    Transport.transaction(transport, fn request ->
      # See Table 11-33 - Mode Encoding
      nonce_mode = <<0::size(2), 0::size(1), 0::size(3), 3::size(2)>>

      nonce_in =
        <<a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
          0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
          0x0D, 0x0E, 0x0F>>

      request.(
        <<@atecc508a_op_nonce, nonce_mode::binary, 0::size(16), nonce_in::binary>>
        |> IO.inspect(as: :binary, base: :hex),
        29,
        1
      )
      |> interpret_result()
      |> case do
        {{:ok, value}, _retry} ->
          Logger.info("nonce: #{inspect(value)}")

          # input max 32 byte
          # mode = 0x40 + 0x02 + 0x10
          mode = 0x40 + 0x02 + 0x10
          log_binary(mode, "mode")
          # 0x40 (KDF_MODE_ALG_HKDF)
          # 0x02 (KDF_MODE_SOURCE_SLOT) # we want to use a slotted private key
          # 0x10 (KDF_MODE_TARGET_OUTPUT) output to output
          # 0x14 KDF_MODE_TARGET_OUTPUT_ENC encrypted output

          # slot 0
          # key_id = <<0x00, 0x00>>
          # source slot 8
          key_id = <<0x00, 0x08>>
          log_binary(key_id, "key_id")

          details = <<byte_size(input)::8, 0x00::16, 0x02::8>>
          log_binary(details, "details")

          input_length = byte_size(input)
          rem = (32 - input_length) * 8
          input = input <> <<0::size(rem)>>
          log_binary(input, "input")

          payload =
            <<@atecc508a_op_kdf, mode, :binary.decode_unsigned(key_id),
              :binary.decode_unsigned(details), :binary.decode_unsigned(input)>>

          log_binary(payload, "payload")

          # output_size = <<32,0,0,0>> |> :binary.decode_unsigned()
          request.(payload, 128, 32)

        # request.(payload, 128, 64)

        {error, _retry} ->
          error
      end
    end)
    |> interpret_result()
  end

  defp log_binary(bin, label) when is_integer(bin) do
    log_binary(<<bin>>, label)
  end

  defp log_binary(bin, label) do
    Logger.info(
      "#{label}| hex: #{inspect(bin, as: :binary, base: :hex)} bin: #{inspect(bin, as: :binary, base: :binary)} [#{inspect(byte_size(bin))}]"
    )
  rescue
    _ ->
      Logger.error("Could not print: #{inspect(bin)}")
  end

So the nonce call input is not particularly important now. I could make that random or based on input. The current setup, the nonce input ends up in the TempKey area. If I set 0x00 instead of 0x02 I can have that be my salt for the KDF. Not what I want. Ideally I’d like to use output 0x14 for encrypted output instead of 0x10 also don’t have that working.

Made some progress this evening where I realized the ATECC is very particular about ECC private keys, with good reason. So it won’t let me use those for this. Presumably that would let me do some kind of mathematical attack to figure out what they are. So there are limits.

Using the wide-open settings slots that NervesKey configures I could actually make the slot work, assuming I put some data in there and that became my salt. If I can put a secret in a writable slot and lock it to be private with some non-ECC just-very-private data in it that should be good for what I want done.

And I think I saw something indicating that the encrypted output is only available for a locked slot. Not sure, that might be speculation on my part but I will attempt to figure it out. I think the encrypted output is the “IO protection” and I hope that doesn’t require the Secure Boot approach they have. I plan to f around and find out.

lawik

lawik OP

Nerves Core Team

Now I tried something novel. There is an area called TempKey which is entirely internal to the chip. It can’t be read from outside.

I used the ecdh to generate a pre-master secret into that space. But it doesn’t seem to be valid for the kdf generation. I can set TempKey via the nonce request and then use it to do kdf.

I don’t think I can use sign_digest to put a useful value in TempKey because that request doesn’t seem to have TempKey as an option.

I think the issue with the ecdh value is probably that it is marked as an ECC key or similar and that makes the chip refuse to use like this. But I’m not sure. It all looks like :execution_error from here.

lawik

lawik OP

Nerves Core Team

This document under 5.1.6.2 describes the Encrypted Read which I think is the first proper description I’ve found of what it takes to get IO protection.

lawik

lawik OP

Nerves Core Team

Except of course for KDF where encryption is baked in (optionally) according to 5.3.4.4.

lawik

lawik OP

Nerves Core Team

Okay, I can’t say I see the point of the IO protection. I guess you could safely write the shared key inside the ATECC and get it to not be externally readable? But you can’t do that on most MCUs (which is the intended use-case) or on the RPi devices I’m dealing with currently. So the shared secret is not that hard to extract meaning the IO protection is a layer of inconvenience but it isn’t really anchored to anything. Probably not enough to be worth bothering with.

And also, it seems it would require a change in config for the NervesKey. Possibly a compatible one but yeah, not convinced about that functionality.

— All posts loaded —

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 92995 915
New
AstonJ
The obligatory hello world thread! Who are you and where are you from? :stuck_out_tongue:
4616 55835 594
New
caslu
I want to open this thread for you all to discuss and help those who really like Ash but are still hesitant to use it in a real project. ...
New
Herve37
We’re evaluating API mocking tools for OpenAPI-based projects and would love to hear what other teams are using. We’re particularly inte...
New
matt-savvy
Is there a word for the ~> symbol used in Version strings? Do you also just call it a Squiggle Arrow™ ?!
New
GES233
I’m posting this in response to Jose’s recent tweet (Cr. link) : People are sleeping on Elixir for a coding harness: Hot-code swappi...
New
nseaSeb
AcmeScript — Writing JS hooks as if I were still using Elixir I’ve been having fun building a little something over the last few days: Ac...
New

Other Trending Topics Top

garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New
webofbits
Aludel - LLM Evaluation Workbench Aludel is an embeddable Phoenix LiveView dashboard for evaluating and comparing LLM prompts across mult...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews