Teddycloud CC3200 newbie guide

:bangbang: Read the official documentation as well :bangbang:
:bangbang: Proceed at your own risk (which is quite low) :bangbang:

:small_orange_diamond: Intro :small_orange_diamond:

This guide aims to concentrate all the information necessary to get your toniebox up and running with teddycloud. The individual places, where you can find the information are well written and explain everything. When I started out it was difficult for me to put everything together in the right order. Thus the motivation for this guide: providing a one stop place, where you can find all the information you need with links to where you can get in depth information.

I will assume some basic knowledge regarding the command line and docker. Some steps where there may be pitfalls are explained in more detail, however I cannot walk you through every single step in detail. This will not be a guide on how to setup docker, pi hole, portainer or the likes.

:small_orange_diamond: Explanation & Goal :small_orange_diamond:

What’s the goal of this whole project? And how does Teddycloud work at all?
Well, an unmodified Toniebox is communicating with the official Toniecloud (by Boxine) for example to download any audio content (besides other things). So when you put a Tonie on the box, the real content of the audiobook will be downloaded from the Toniecloud (once) and is stored on the Toniebox for offline listening. The communication between the Toniebox and the Toniecloud takes place on a secured HTTPS connection, so certificates are needed on both sides (server/client). Without going too much into technical details, this is a simplified overview:

Now think of our self-hosted Teddycloud as a man-in-the-middle between the Toniebox and the Toniecloud. So at the end of this tutorial, the Toniebox won’t communicate with the Toniecloud/Boxine anymore but only with the Teddycloud. The Teddycloud itself needs to pretend to be a real Toniebox in order to be allowed to communicate with the original Toniecloud. And in order to achieve this, we need to extract the client certificates from our Toniebox and store them in Teddycloud so that from now on our Teddycloud looks like a real Toniebox from Boxine’s point of view. Without the client certificates, the original cloud won’t let Teddycloud download any content and not even establish a coummunication.

As a last step, the Toniebox needs to communicate with our new Teddycloud and this also needs to take place in a secured HTTPS way. That’s why we have to use a (self-generated) CA certificate on the Teddycloud Server and this certificate has to be known by the Toniebox as well (because never trust a stranger). So we need to replace the original CA certificate (from Boxine) with our self-generated one of the Teddycloud. Technically with the custom bootloader and the available patches we may run both certificates on the toniebox. The custom bootloader allows to simulate original firmware behavior and load the same image like the original firmware would, but with patches applied.
In addition to that, we run the toniebox with a patch that changes the original domains to a non-public domain that resolves to our teddycloud instance.

:small_orange_diamond: Tools :small_orange_diamond:

:small_orange_diamond: Preparation & Setup :small_orange_diamond:

Toniebox:

If your Toniebox is brand new, please connect it to your WiFi and so that the latest software update can be installed. Tutorial, you don’t need a tonies account for that.

Install required software:

In this example I will use a windows machine where I connect a UART programmer and a virtual machine running ubuntu, that runs my docker instance. I didn’t want to passthrough the programmer to the VM in order to not an additional layer of complexity. Probably it would have been fine.
I will not differentiate between the current directory on the windows machine and the linux machine, if you run a similar setup I assume you know how to move files between the two of them (scp, a smb share, …)

  1. Download python with the UI installer, check to add python to PATH
  2. Install git; add to path if you want
  3. (optional) install pip, for me it was already included with the python installation
  4. Install cc3200tool, depending on whether you added git to PATH either use the command line or launch git cmd. Then enter
pip install git+git://github.com/toniebox-reverse-engineering/cc3200tool.git

For me, it did not resolve and I had to change it to

pip install git+https://github.com/toniebox-reverse-engineering/cc3200tool.git

Now continue on the machine you want to run docker on. For me it’s a VM on my server:

  1. install docker and optionally docker compose.
  2. optional install Portainer
    highly recommended in order to manage your docker environment with a GUI, check the logs etc.
  3. install Teddycloud
    Open the portainer webui, select your local environment and then choose stacks in the menu on the left. Stacks is the equivalent of docker-compose. Click on “Add Stack”, name it “teddycloud” and paste the following content:
services:
  teddycloud:
    container_name: teddycloud
    hostname: teddycloud
    image: ghcr.io/toniebox-reverse-engineering/teddycloud:latest
    ports:
     - 80:80 #optional (for the webinterface)
     - 8443:8443 #optional (for the webinterface)
     - 443:443 #Port is needed for the connection for the box, must not be changed!
    volumes:
      - certs:/teddycloud/certs
      - config:/teddycloud/config
      - content:/teddycloud/data/content
      - library:/teddycloud/data/library
      - firmware:/teddycloud/data/firmware
      - cache:/teddycloud/data/cache
    restart: unless-stopped
# needed if using macvlan
#    networks:
#     - myteddycloud-creation
volumes:
  certs:
  config:
  library:
  firmware:
  cache:
  content:
# needed if using macvlan
#networks:
#  myteddycloud-creation:
#    external: true

If you don’t use portainer, save the contents to a directory of your liking and name it docker-compose.yml then start the container with docker compose up -d.

Important:
From what I gathered teddycloud requires to not be used with a reverse proxy. I used portainer to create a macvlan network.
This video (in german) explains it very well. Basically you can follow along starting at 5:43. If someone knows a good video in english, please comment. I will assume you have some basic understanding of docker, so hopefully you will be able to follow along.

Optional:
Instead of creating volumes you can also bind mount via

/some/path/on/host/library:/teddycloud/data/library
/some/path/on/host/certs:/teddycloud/certs

and omit the corresponding volumes. For me it’s easier to have access to these folders via my main maschine (over samba share) rather than going into my VM, that is running docker.

:small_orange_diamond: Connect flash chip with programmer :small_orange_diamond:

We have to open the box and obtain the plain mainboard without any connected cables attached. The process is the same as for ESP32 boxes like shown in this video (starting 14m58s): https://youtu.be/JpMRyshgy9o?t=899
Use an appropriate tool (or used two small screwdrivers) to release the battery connector. You don’t want to pull out the thin cables!

Be aware that the board is connected to the RFID reader with 6 pins at the bottom right side (the opposite side of the headphone jack)! So when trying to remove it, make sure to push it upwards (to the top) to avoid bending these pins by accident.

rfid-pins

Now it’s time to make the connection to the debug port. As mentioned earlier I opted for the resistor clip offs method. I just used pliers to clip of the pins of a few resistors I had lying around.

@baumeisterde soldered the connections and used a female pin header.

I carefully placed my pins and used a multimeter to ensure connection / no shorts:

and hot glued it afterwards to make sure they don’t move during flashing. This was the easiest method for me. More expensive / more elaborate methods do exist as stated before. I used crocodile clamps and jumper cables to connect to the UART programmer.



:small_orange_diamond: Read, patch & write the certificate/firmware :small_orange_diamond:

:bangbang: Make sure your UART programmer runs at 3.3V! Measure with a multimeter to make sure.

Connect the UART programmer via USB to your computer. The green LED of the Toniebox mainboard should be constantly green (no flashing/blinking). If that’s not the case, your connections are most probably not sitting correctly. Before you try it again, unplug the programmer first!
I additionally supplied power to the toniebox (after I checked the programmer is connected correctly) via the charger.

All steps are taken from the wiki.

I try to streamline the process as much as possible. Basically we will perform the following steps:

  • Extract certificates from toniebox and place them in teddycloud
  • Flash certificate from teddycloud
  • Along the way we will install the custom bootloader

For a better readability I chose to hide all steps in a details box so you don’t get overwhelmed with all the commands. Expand each step to follow it:

1 Backup

Open a terminal and navigate to a folder you want to work in and enter (check your paths!)

cc3200tool -p COM3 read_all_files ExtractedFromBox/ read_flash backup.bin

I will refer to the full path of your current directory as /currentDir in the future.

Make sure you selected the right COM port and if your UART programmer has a DTR pin use --reset dtr before each command (cc3200tool -p COM3 --reset dtr ...). Otherwise you need to briefly connect RTS to GND before each command.

For me, there were some files that did not exist on the box, thus the command exited with an error and never properly created the backup.bin.

I recommend going

cc3200tool -p COM3 read_all_files ExtractedFromBox/
cc3200tool -p COM3 read_flash backup.bin

Verify your results! Make sure backup.bin is not 0 kb.

2 Get the server certificate and upload client certificates

2.1
Copy the server certificate with a method of your choice. I like to work with the host paths:

Get your volume paths:

docker inspect -f '{{range .Mounts}}{{ if eq .Type "volume" }}{{println .Source }}{{ end }}{{end}}' teddycloud

Output:

/var/lib/docker/volumes/teddycloud_content/_data
/var/lib/docker/volumes/884******4bf/_data
/var/lib/docker/volumes/teddycloud_firmware/_data
/var/lib/docker/volumes/teddycloud_library/_data
/var/lib/docker/volumes/teddycloud_certs/_data
/var/lib/docker/volumes/teddycloud_config/_data
/var/lib/docker/volumes/teddycloud_cache/_data

So the certificates of Teddycloud are stored in
/var/lib/docker/volumes/teddycloud_certs/_data on the host system.
Save your certificate.

sudo cp /var/lib/docker/volumes/teddycloud_certs/_data/server/ca.der /currentDir/server/ca.der 

Refer to this post for an explanation and alternative.

2.2 (optional)
If your machine running docker (dockermachine) is not the same as the one you connected the UART programmer (UARTmachine) to, you need to transfer the files between the two systems.
Assuming you connect to your machine running docker via SSH, you could use scp to transfer the files or you work in a shared directory (samba share for example). If you don’t need an explanation or don’t work with two machines, proceed with 2.3.

For scp you need openSSH, install that on your machines if they don’t ship with it.
Example using scp, indicating on which machine the command is executed:

# Since we need elevated privileges to access /var/lib/docker we need to copy the file to a directory we can access without sudo
name@dockermachine:~$ sudo cp /var/lib/docker/volumes/teddycloud_certs/_data/server/ca.der /dirForTransfer/server/ca.der 
# Now we download the file to our UARTmachine
name@UARTmachine:~$ scp username@dockermachine:/dirForTransfer/server/ca.der /currentDir/server/ca.der

2.3
Depending on your paths you know should have something like this in your present working directory (where you started cc3200tool):

currentDir
│   backup.bin
├───ExtractedFromBox
└───server

2.4
Now upload the client certs to teddycloud:

sudo cp -r /currentDir/ExtractedFromBox/cert/. /var/lib/docker/volumes/teddycloud_certs/_data/client/

Newbie frienldy: Or use the webGUI of your teddycloud instance:

Navigate to http://IP.OF.TEDDY.CLOUD/web/settings/certificates and upload:

2.5 (optional)
Example as shown in 2.2 using scp, indicating on which machine the command is executed:

# Copy the client certificates to the docker machine
name@UARTmachine:~$ scp -r /currentDir/ExtractedFromBox/cert/. username@dockermachine:/dirForTransfer/client/
# Since we need elevated privileges to access /var/lib/docker we need to copy the file from our temporary transfer directory we just uploaded to
name@dockermachine:~$ sudo cp -r /dirForTransfer/client/. /var/lib/docker/volumes/teddycloud_certs/_data/client/
3 Flash c2.der
cc3200tool -p COM3 write_file server/ca.der /cert/c2.der

Make sure you selected the correct path to the ca.der you extracted from teddycloud.

4 Follow the installation for the bootloader

This is well explained in the wiki so please refer there

4.1
Download the bootloader here.

Unzip and you get two folders: sd and flash.

4.2
First of all you need to copy your just backuped original mcuimg.bin (original bootloader) from your toniebox to a different location (flash:/sys/pre-img.bin) to boot it with the HackieboxNG Bootloader later on. Please don’t confuse the mcuimg.bin (ofw bootloader) you are going to dump with the mcuimg.bin within the hackiebox zip package. (/flash/sys/mcuimg.bin)

We already made a full backup so we can find mcuimg.bin under

/currentDir/ExtractedFromBox/sys/mcuimg.bin since you should still be running cc3200tool from that directory write the file to the toniebox:

cc3200tool -p COM3 write_file ExtractedFromBox/sys/mcuimg.bin /sys/pre-img.bin

and install the preloader:

cc3200tool -p COM3 write_file flash/sys/mcuimg.bin /sys/mcuimg.bin

the path depends on where you placed the files from the bootloader.

4.3
We are done using cc3200tool. Personally I would disconnect power from the box now and disconnect the programmer’s USB connection so the box has no power. Now remove the SD card. There is some glue in front of it. Clean it up and then you can push the metal cover slightly forward and then pull it up. Then you can remove the SD card.

Copy over all the contents of the sd folder to the sd card of the toniebox. Copy over the original bootloader (mcuimg.bin from your backup) to the first ofw slot sd:/revvox/boot/ng-ofw1.bin . Now the HackieboxNG bootloader will instantly boot the original bootloader and run the original firmware.

I opted not to use the custom firmware, however in order to avoid having to disassemble the box again in the future I download the firmware from here.

And followed this step from the readme:

First of all you need to create “/revvox/web” on your sd card (subdir revvox should be already there if you have successfully installed the sd bootloader) and copy over the content of the /web/ directory of this repository. The same applies to the “/revvox/audio” directory for WAV-playback during the battery test. In addition you have to copy your cfw image to your selected slot(s) on the sd card. (ex. “/revvox/boot/ng-cfw1.bin”)

In order to have a second copy of the cfw according to the readme, I also placed it under /revvox/boot/ng-cfw2.bin. I didn’t boot it afterwards, refer to the wiki for further instructions.

5 Edit ngCfg.json

We are going to make some edits to our file on the SD card we just copied.

    "ofw2": {
        "checkHash": true,
        "hashFile": false,
        "watchdog": true,
        "ofwFix": true,
        "ofwSimBL": true,
        "patches": ["altCa.305", "altUrl.tc.fritz.box"]

Choose whether to use the tc.fritz.box patch or the altUrl.305 patch and choose the right patch for you under “patches”.

I also chose to always boot the ofw with applied patches so ofw2:

{
    "general": {
        "activeImg": "ofw2",

This is well explained in the wiki so please refer there.

Since i personally used the altUrl.305 patch I added local DNS entries in my pi hole instance for
prod.revvox and rtnl.revvox. Since there’s a multitude of options on how to achieve custom DNS entries I will not explain this step in detail.
Pihole is set as the DNS resolver in my fritzbox so all devices get assigned my pihole instance as a DNS server.

6 Reassemble

Disconnect everything and reinsert SD card in the toniebox. Now you can connect the speakers and ears and battery again.
You can fire up the box now and see if it’s working as intended. If everything works you can reassemble the box completely.

You’re done - you should now be able to use your own teddycloud.

7 Optional

Using the current version tc_v0.6.2 will lead to the following error in your logs:

ERROR|tls_adapter.c:0189:read_certificate| Failed to open '/teddycloud/certs/client/78dXXXXXX12fd/ca.der' for cert type detection
ERROR|tls_adapter.c:0376:load_cert| Loading cert '/teddycloud/certs/client/78dXXXXXX12fd/ca.der' failed
ERROR|tls_adapter.c:0189:read_certificate| Failed to open '/teddycloud/certs/client/78dXXXXXX12fd/client.der' for cert type detection
ERROR|tls_adapter.c:0376:load_cert| Loading cert '/teddycloud/certs/client/78dXXXXXX12fd/client.der' failed
ERROR|tls_adapter.c:0189:read_certificate| Failed to open '/teddycloud/certs/client/78dXXXXXX12fd/private.der' for cert type detection
ERROR|tls_adapter.c:0376:load_cert| Loading cert '/teddycloud/certs/client/78dXXXXXX12fd/private.der' failed
INFO |tls_adapter.c:0390:tls_adapter_init| Loading certificates...

As was explained to me by @0xbadbee teddycloud will use the certificates under /teddycloud/certs/client/ as a fallback so everything should be working.

If you want to resolve the issue you can create the directory 78dXXXXXX12fd (UID of your toniebox) yourself.

For example (choose any other way you see fit) either find the host path for the docker volume and copy the certificates yourself also in /teddycloud/certs/client/78dXXXXXX12fd/ or connect to the container and do it within the container.

Find container name with

sudo docker ps | grep teddy
sudo docker exec -it teddycloud bash

inside the container do:

cp /teddycloud/certs/client/private.der /teddycloud/certs/client/dcda0c002b68/private.der

repeat for the other two and then exit.

Next reboot it shouldn’t be a problem anymore.


Thank you @marco79cgn for allowing me to copy large portions of your cc3235 guide!

If you have any feedback, questions, corrections feel free to let me know!

2 Likes

The patches are done during the starting process of the firmware in RAM. So this is technically wrong! You only need to install the custom bootloader hackiebox ng for that.

Rest looks good to me, thank you for sharing!

Thanks! I edited that part. This was still taken from the cc3235 guide and I must have missed it.

[quote=“chuckf, post:1, topic:925”]
read_all_files
[/quote]I just read this guide and found that my backup.bin is 0kb. The other files that were saved with the read_all_files command are ok and complete. Can the backup.bin be backed up or created later? Is this necessary to go back to the original firmware? Toniebox was successfully flashed with Hackiebox bootloader.

@chuckf can you have a look here, i mixed up all things to add the cc3200 guide also in TC directly. Just to confirm that it should work roughly :wink:

Thank you @henryk ! You have worded some parts better than I did, I’ll probably update my guide here and there but from what I see I can confirm that everything looks correct.
I would maybe add that you should ensure somehow that the thin wires do not move / touch during using the programmer. At least for me they were still easily moved, that’s why I opted for hot glue.

@MuckyDerMuck I see that you already created a new topic regarding your backup.bin and are already receiving help there.

Thank you for this guide. I try to follow it, but I have some questions.

I am hard stuck at the docker part. I do not use docker other than for the teddycloud so I am lost here.
I installed docker and portainer on a proxmoxx server and deployed teddycloud.
Now I need the certificates. Where do I put the commands under 2? How do I access the files?

edit: ok, I managed to find access the files: I reinstalled docker, enabled ssh and then copied the files via sftp client to my pc.

edit2: I get the error elephant (no connection to wifi) and can’t see the tonie box in my network. As patch I used
"patches": ["altUrl.tc.fritz.box"]
and changed the docker servername to tc. But it does not connect

More specifically it’s pointing to invalid credentials. Did you change the wifi password since first setting up the box?

I’m not sure what’s the best approach here.

I see two ways here:

a) load the ofw1 without patches and use the setup assistant
b) or do it without the setup assistant.

I’d probably go with option b).

I’m not sure whether the credentials are stored in a json file on the sd card.

Minus the reinstall this is the way.

Maybe I have to update the guide in that part to at least give one working example, I assumed anyone running docker on a different machine would have means to move files around.

With SSH enabled you could use scp:

Upload from local machine (e.g. windows pc) to remote machine (raspberry, linux VM, …)

scp /file/on/local/machine username@remote:/file/on/remote/machine

download

scp username@remote:/file/on/remote/machine /file/on/local/machine

I chose option b. My box is now connected to the teddycloud. Thank you for the Guide and the help.

1 Like

I wanted to flash my second box but I am not sure what to do here:

do I just replace the cert files on the tc server with the ones from the second box?

the certs/cllient are used for teddycloud to communicate with boxine cloud.
For each box the certs are stored in a folder with the mac adress:

certs/client/
certs/client/

grafik

this is the content of my tc_certs folder
So do I just need to upload the certs from my second box and overwrite the old? Or do I have to create ne folders? I can not find any mac adress information

Those are used for the passthrough to the boxine cloud. You don’t need to anything with them.

You could check your UID of your box, create a subfolder and also store them there. See 7 Optional

You get the ID from the webUI / docker logs.

See this thread: Path for certificates not correct - #3 by chuckf

You’ll need to create a subfolder for each box. This can be seen in the Toniebox Settings in the WebGUI.

I created a folder with the UID of the second box and uploaded the certs. And I fixed a spelling error in the ngCfg.json :face_with_peeking_eye:, rebooted the box and tc could find it and I was able to add it.
Thank you for your help.

added that hint.

ChatGPT is perfect for such things ^^

I updated some images and I added two working examples under Section 2 Get the server certificate and upload client certificates showing how to move files around using scp.

(post deleted by author)