Teddycloud CC3235 Newbie HowTo

Hi there,

within this post I try to make a documentation how to set up Teddycloud on a CC3235 Box.

: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:

Only two weeks ago I bought my first Toniebox ever with the goal to patch it and run Teddycloud. I finally succeeded but the process was a LOT of trial & error. Furthermore I had to search and read on dozens of different places in order to get & understand the whole picture and to find solutions for my problems (and misunderstandings). That’s why I decided to write a complete HowTo in order to help other people to get it done as well. Especially after the YouTube Tutorial from myDealz (for the ESP32 boxes) a lot of people asked for a complete guide which is also suitable for “normal” people (not only IT nerds). I used the Teddycloud ESP32 Newbie Documentation from @Wurst420 as a template and adapted it for the CC3235. This box is said to be more difficult to handle but at the end, it’s not so complicated at all.

: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 patch the original firmware of the Toniebox and replace the original CA certificate (from Boxine) with our self-generated one of the Teddycloud. Finally this patched firmware has to be written to the flash chip of the Toniebox. In addition to that, we have to change our local DNS for the Toniebox and point a public url to our Teddycloud instance. This is necessary because besides the CA certificate, we don’t change a single thing in the original firmware. So when our Toniebox wants to connect to the Toniecloud (prod.de.tbs.toys) after we put a Tonie on it, this call should not lead to the official server (Boxine) but to our local Teddycloud.

The Teddycloud itself on the other hand needs to resolve the official Boxine server, so we have to make sure that our DNS change is not effective for the Teddycloud instance. Of course It’s up to the enduser to decide whether the original Toniecloud should be used in the first place. This feature actually is turned off by default. But you have to activate it if you want to continue using original Tonies and download/listen to their original audio content. Be aware that the Teddycloud already filters a lot of unnecessary traffic between the Toniebox and the Toniecloud, like analytics data (how often you listen to what etc.). And even if you never plan to use the Toniecloud again, you still have to patch the firmware of the Toniebox so that it can establish a secure connection with your Teddycloud.


:small_orange_diamond: Tools :small_orange_diamond:

I will make use of Docker in this tutorial and try to cover every single step needed. I’m using a Raspberry Pi running the official Raspberry Pi OS (bookworm) and the Lite Version which is headless, so there is no graphical window management/Desktop. But the full version also works just fine. All steps in this HowTo will take place in a Shell/Terminal session from the command line. So either SSH into your Raspberry Pi (headless) or use the Terminal App. Be aware that every other Linux distribution and even Windows should work as well. For this guide we’ll use a CH341A programmer since it’s cheap and easy to get. As always, Ali Express is the cheapest option but I bought my set at Amazon:
Amazon.de

:small_orange_diamond: Preparation & Setup :small_orange_diamond:

Toniebox:

If your Toniebox is brand new, please set it up with the official Tonies App. Make sure that it is connected to your WiFi and that the latest software update is installed.

Raspberry Pi:

  1. Set up Raspberry Pi OS and install the latest updates:
    sudo apt update && sudo apt upgrade

  2. install Docker
    curl -sSL https://get.docker.com | sh
    sudo usermod -aG docker $USER

  3. install Portainer
    highly recommended in order to manage your docker environment with a GUI, check the logs etc.

  4. install Python & CC3200 Tool
    Python is needed for the CC3200 Tool. We need this tool in order to patch the extracted firmware from our Toniebox. The original Boxine CA certificate will be replaced with the CA certificate which we will create with the gencert.sh script (in a later step). Python has its own package manager named pip. Because Raspberry Pi OS already has the apt package manager, we need to create a virtual environment for Python so that those two managers won’t conflict with each other.

sudo apt install python3-pip
sudo apt install python3-venv
python3 -m venv .venv
source .venv/bin/activate
pip install git+https://github.com/toniebox-reverse-engineering/cc3200tool.git
  1. install Flashrom
    Not needed on a Raspberry Pi because it’s already prebundled. Otherwise run:
    sudo apt install flashrom

  2. install Teddycloud
    Open the Portainer GUI (https://192.168.178.10:9443), 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:

version: '3'
services:
  teddycloud:
    container_name: teddycloud
    hostname: teddycloud
    image: ghcr.io/toniebox-reverse-engineering/teddycloud:latest
    dns:
      - 1.1.1.1
    ports:
     - 80:80
     - 8443:8443
     - 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
volumes:
  certs:
  config:
  content:
  library:
  firmware:
  cache:
  1. Generate certificates
    At the first start of Teddycloud, it will create the needed server certificates automatically. Unfortunately there is a problem with these certificates and they are not usable for the CC3235 chip. So we won’t use the generated ones but we will create new certificates by ourself and replace the ones from the first start (Step 8).
cd && mkdir toniebox && cd toniebox
wget "https://raw.githubusercontent.com/toniebox-reverse-engineering/teddycloud/master/contrib/gencerts.sh" -O gencert.sh
chmod 755 gencert.sh
./gencert.sh
  1. Copy certificates to Teddycloud
    From the previous step, we only need 3 files from the server directory (/home/pi/toniebox/certs/server), which are ca.der, ca-key.pem and ca-root.pem.
    All other generated files can be ignored! We will copy them to the correct folder of Teddycloud and restart Teddycloud afterwards:
docker cp ~/toniebox/certs/server/ca.der teddycloud:/teddycloud/certs/server/ca.der
docker cp ~/toniebox/certs/server/ca-key.pem teddycloud:/teddycloud/certs/server/ca-key.pem
docker cp ~/toniebox/certs/server/ca-root.pem teddycloud:/teddycloud/certs/server/ca-root.pem
docker restart teddycloud


: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

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

We need the SOP8 board from our programmer’s set which is labeled 25XXX and has 8 pins on each side of the board. The ribbon cable needs to be plugged on this board making sure that the red cable is connected to Pin 1.

Now we need to plug the other side of this board onto the programmer. With the programmer lying in front of us and the USB-A plug pointing upwards (like in the picture), please make sure to put the pins of the SOP8 board into the upper 8 wholes of the programmer. You need to open the little arm first by putting it upwards, pointing to the sky. The red cable has to be placed downwards. It shuold look exactly like this:

Now with the mainboard separated and lying in front of you, locate the IS25LP032 chip. This is where the clamp has to be connected to. Pin 1 of this chip is marked with a round black circle. Make sure that the red cable on the clamp will be connected to Pin 1.

Most probably you will have to cut a part of the plastic enclosure of the clamp because there is another chip right next to the flash chip which makes it impossible to get the clamp connected to the flash chip properly. I used a carpet cutter to trim it.

It is very important that the clamp sits tight and correct! It might take a few tries to get it on. Make sure that it looks like this before connecting the programmer to the Raspberry Pi:


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

Connect the CH341A USB programmer to the Raspberry Pi. The green LED of the Toniebox mainboard should be constantly green (no flashing/blinking). If that’s not the case, your clamp is most probably not sitting correctly. Before you try it again, unplug the programmer first! Be aware that you don’t need to connect the battery or the power outlet to the Toniebox mainboard. It will be powered via USB by the CH341A programmer.

  1. Now let’s check if the programmer is recognized by the Raspberry Pi.
    Type lsusb in the Terminal and the output should list your usb programmer:
pi@raspi:~/toniebox/certs $ lsusb
Bus 004 Device 012: ID 1a86:5512 QinHeng Electronics CH341 in EPP/MEM/I2C mode, EPP/I2C adapter
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
  1. Read the original firmware from the Toniebox with this command:
    sudo flashrom -p ch341a_spi -r backupCC3235.bin
    If everything went smooth, the output should look like this at the end:
    Reading flash... done.

  2. Verify firmware
    To double check that the firmware has been dumped successfully, check the size of the backupCC3235.bin file. It should be 4 MB. You can also check the content of the dump using the strings function. The output should look like this:

pi@raspi:~/toniebox/certs $ ls -lah
total 4.0M
drwxr-xr-x 3 pi pi 4.0K Nov 10 18:19 .
drwxr-xr-x 4 pi pi 4.0K Nov  6 00:33 ..
-rw-r--r-- 1 pi pi 4.0M Nov  7 16:09 backupCC3235.bin

pi@raspi:~/toniebox/certs $ strings backupCC3235.bin | grep "Boxine GmbH Root CA"
 Boxine GmbH Root CA Code Signing0 
 Boxine GmbH Root CA Code Signing0
 Boxine GmbH Root CA Code Signing0 
  1. Extract certificates from dumped firmware
    Now we’ll extract the certificates from the dumped firmware using the CC3200 Tool.
pi@raspi:~/toniebox/certs $ source ~/.venv/bin/activate
pi@raspi:~/toniebox/certs $ cc3200tool -if backupCC3235.bin -d cc32xx read_all_files extract/
  1. Copy client certificates to teddycloud
    The extracted client certificates from the previous step should now be located in the ~/toniebox/certs/extract/cert folder. We need to copy them to the Teddycloud cert directory so that from now on the teddycloud can act like it would be our real Toniebox.
docker cp ~/toniebox/certs/extract/cert/ca.der teddycloud:/teddycloud/certs/client/ca.der
docker cp ~/toniebox/certs/extract/cert/client.der teddycloud:/teddycloud/certs/client/client.der
docker cp ~/toniebox/certs/extract/cert/private.der teddycloud:/teddycloud/certs/client/private.der
docker restart teddycloud
  1. Patch original firmware
    Communication with the real Toniecloud will be exclusive to Teddycloud from now on. Our Toniebox should not communicate with the original Toniecloud (Boxine) anymore. The Teddycloud is so to say the man-in-the-middle between our Toniebox and the Toniecloud. In order to make our Toniebox communicate with our self-hosted Teddycloud, we have to patch the server certificate (CA) of the Teddycloud (which we created with the gencert.sh script earlier) into the firmware of the Toniebox. This is absolutely necessary so that the Toniebox can communicate with our Teddycloud secured via https, like it did before with the original cloud. Therefore we have to replace the Boxine CA in the original firmware with our self-generated CA certificate. The replacing can be done with the CC3200 Tool as well:
pi@raspi:~/toniebox/certs $ cc3200tool -if backupCC3235.bin -of cc3235-flash.customca.bin -d cc32xx write_file /home/pi/toniebox/certs/server/ca.der /cert/ca.der
  • command parameters explained:

-if backupCC3235.bin → input file (our dumped original firmware)
-of cc3235-flash.customca.bin → output file (which we will write onto the chip later)
/home/pi/toniebox/certs/server/ca.der → path of our generated Teddycloud certificate - replace piwith your user if necessary! (full path needed here)
/cert/ca.der → path inside the firmware (don’t change it!)

  1. Write patched firmware to the flash chip
    In the final step we’ll write the patched firmware to the flash chip of the Toniebox using flashrom:
pi@raspi:~/toniebox/certs $ sudo flashrom -p ch341a_spi -w cc3235-flash.customca.bin
  1. Disconnect mainboard
    The programmer can now be unplugged from the Pi and afterwards(!) the clamp from the flash chip as well.

  2. Change DNS
    Set the DNS entries for prod.de.tbs.toys and rtnl.bxcl.de to the local ip-address of your Teddycloud instance (Raspberry Pi). There are different solutions depending on your home setup. I’m using Pihole as DNS in my local network so the simplest solution for me was to edit the /etc/hosts file on my Pihole and adding two lines:

192.168.178.11  prod.de.tbs.toys 
192.168.178.11  rtnl.bxcl.de
  • There are also solutions for AdGuard and OpenWRT which you can find in the official Teddycloud GUI (Add Toniebox → CC3235 → DNS tab). Be aware that this step is very important and you have to find a way to configure the DNS for these two domains. Otherwise the Toniebox won’t connect to Teddycloud (Codword: Owl). Unfortunately it’s not possible with the CC3235 box to flash those DNS rules directly in the box firmware (like the ESP32).
  1. Reassemble and Test
    Before you reassemble your box completely, connect only the three cables (speaker, buttons & battery) in order to start the Toniebox. Open your Teddycloud GUI in the Browser and check whether your Toniebox is recognized. Go to http://192.168.xxx.xxx/web/tonieboxes/boxsetup/cc3235/flashing, click through the end and push the “Show available boxes” button. Have fun!

ㅤㅤㅤ


Big thanks to Team revoxx and inonoob for his great CC3235 tutorial (which makes it to the official teddycloud v0.6.3 tutorial) and his help on github.


:small_orange_diamond: Troubleshooting / FAQ: :small_orange_diamond:

:speech_balloon: Glibberish output or no connection when trying to read the flash chip

Recheck the connection of the clamp on the flash chip. Make sure it is aligned properly. Verify that the Toniebox LED is constantly green and the power LED of the programmer is red. Also make sure that lsusb still shows your programmer as soon as the clamp is connected to the board. The first programmer I bought was faulty (dead on arrival) and disconnected as soon as the clamp was sitting perfectly fine.

:speech_balloon: My Toniebox won’t connect to Teddycloud

Check the logs of your Teddycloud container. You can do this either by clicking the “Logs” button in Portainer → Containers → teddycloud or by using the Terminal with the following command:

docker logs -f teddycloud 

Make sure that the certificates are correctly parsed.

:speech_balloon: Refreshing the box leads to error code “owl” (Eule)
Either you flashed the wrong certificate (or a broken one) or your box is still communicating with the Boxine Toniecloud directly. Make sure to set the DNS correct and effectively (Step 10).

:speech_balloon: How can I update my teddcloud instance?

In Portainer, select “Images” from the menu, choose your teddycloud image and push the “pull from registry” button.

:speech_balloon: How can I switch to devleopment builds?

In Portainer → Stacks → teddycloud choose the “Editor” tab and change the image tag at the end:

image: ghcr.io/toniebox-reverse-engineering/teddycloud:develop

Click on “Update the stack” to apply the changes.


That’s it I guess. Any feedback or corrections appreciated! Have fun.

3 Likes

First, thank you for writing this guide. This may help others!

Some small adjustments:

Typo

This is not the reason for that. The problem is, that the CC3235 needs something special in the CA. But we don’t know. The teddyCloud generated ones don’t work. But it works with the legacy gencert.sh

Great work!

I struggled a bit to get everything in right order although all the information was there for CC3200 in the wikis. I mentioned in another post that I’m thinking about creating a step by step instruction for other beginners.

I don’t see too much value in explaining all the steps in detail again that are already mentioned here. Would you be open to collaborate on the guide and I would add cc3200 specific bits for you to include? If you’re interested, shoot me a PM.

@chuckf
Sure we could do that, happy to collaborate. I’m just not sure whether it’s a good idea to put both models in one HowTo because this might lead to confusion or misunderstandings, don’t you think? At first sight, flashing the CC3200 looks even more complex as you first have to flash a custom bootloader etc.

I think I should get a CC3200 box and try this by myself. :slight_smile:

@marco79cgn I can create a separate guide for cc3200 if I may copy & credit information from your post that are relevant for both chips.

I also had some basic questions so I’m not the absolute expert, however after going through the steps I’m fairly confident that I can concentrate all relevant information for beginners in a form I would have wanted when I started out.

Sure, you can take anything you want and I’m glad to help. Actually two of these pictures aren’t from me as well. :slight_smile:

Hi Marco79cgn,

I have a problem with the SOP8 clip and the programmer. My programmer is similar to the one in the YouTube tutorial from Mydealz. Could you please advise me on how to connect it correctly?

First of all, thank you so much for the guide! I got it almost done, but I cant connect the Box to the Teddycloud. I’m stuck at Step 10. I do have a Pi-Hole installed and active on the exact same Raspberry as Docker and Teddycloud. I’ve changed the etc/hosts from the Raspberry Pi but the Box still has the “Owl” error. I also checked that the Toniebox is connected and visible on my Fritz!-Router.

Does Pi-Hole has a different hosts file than the Raspberry itself?
Here’s what the hosts file look like:

127.0.0.1	localhost
::1		localhost ip6-localhost ip6-loopback
ff02::1		ip6-allnodes
ff02::2		ip6-allrouters

127.0.1.1	raspberrypi
192.168.179.65  prod.de.tbs.toys 
192.168.179.65  rtnl.bxcl.de

192.168.179.65 is the IP of my Raspberry. I hope you can help. Thanks in advance

Edit: Some more Infos: teddycloud is succesfully connecting to Boxine, I’m pretty sure flashing went well.

Sorry, I don’t have a clue. Is this a CH340 programmer?

@Martin_Gubin
I had a similar problem at the beginning. If Teddycloud can connect to Boxine successfully, this “only” means that you read your flash chip successfully and obtained valid client credentials from the Toniebox. It doesn’t mean that you also wrote/flashed the Box successfully with your Teddycloud CA certificate. So this might be a possible reason.

Another thing: are you using IPv6 as well ? In my case, I also added the corresponding IPv6 entries to /etc/hosts on the Pihole. Maybe worth a try.

fdc0:ffee:****:****:****:****:****:ef3b  prod.de.tbs.toys
fdc0:ffee:****:****:****:****:****:ef3b  rtnl.bxcl.de

After I did this, I went to a concert and when I came back, my Toniebox worked without the owl error message. So I’m not pretty sure whether the DNS changes just needed some time (maybe the Toniebox is caching previous DNS resolvings for some time?).

Concering your hosts question: The /etc/hosts of your Raspberry Pi which is running Pihole should be the correct one. Pihole has a special order how dns queries are resolved. First blacklist denylist → hosts → dnsmasq.d → upstream dns (if not cached).

//EDIT: Could you use another computer on your network and do a ping? Your result should be the IP of your Pi (192.168.179.65).

~$ ping "prod.de.tbs.toys"                                                             
PING prod.de.tbs.toys (192.168.178.11): 56 data bytes
64 bytes from 192.168.178.11: icmp_seq=0 ttl=64 time=199.645 ms
64 bytes from 192.168.178.11: icmp_seq=1 ttl=64 time=13.384 ms
64 bytes from 192.168.178.11: icmp_seq=2 ttl=64 time=10.236 ms

the ping is showing my raspberry ip. im trying another flash with the certs

There’s another thing you could do before flashing again in order to verify that your modified firmware is valid.

  1. copy your already modified firmware (e.g. cc3235-flash.customca.bin) in a new, empty directory

  2. extract certificates out of this modified firmware:

~$ cc3200tool -if cc3235-flash.customca.bin -d cc32xx read_all_files extract/
  1. read the extracted CA certificate and verify CN = Teddy CA in the output
~$ openssl x509 -inform der -in extract/cert/ca.der -text | grep Subject
        Subject: C = DE, CN = Teddy CA
        Subject Public Key Info:
            X509v3 Subject Key Identifier: 
  1. check if it’s the same CA as your Teddycloud is using
sudo diff extract/cert/ca.der /var/lib/docker/volumes/teddycloud_certs/_data/server/ca.der

Yes exactly. I bought this one.

OK, so I guess we “just” have to compare the PINs to see which should go where. Obviously not all of the 8 pins are needed. You have to put your jumper to 3,3V.

This is how it looks like on the CH341A. So on the blue socket, the upper 8 pins are relevant and number 5 is where the red cable is plugged in.

So afaik this is the mapping for CH341A/CH340G:
MISO (6) → RXD
MOSI (9) → TXD

You can use the web UI of pi hole to set local entries, too. May be easier for future reference.

Does your router ensure that every device on the network will use your pinole instance for DNS resolution? Do you see your tonie box as a client in the pi hole web UI?

ok I hope ive mapped it corectly. Thank you very much

Good point! The DHCP server in your LAN has to explicitly set your Pihole as default DNS for all clients and only the Pihole! Don’t use a second alternative public DNS in your DHCP settings because if there are two, you never know which one the client (→ your Toniebox) is using. This might work sometimes and sometimes not.

First of all, thanks for all the replies. Unfortunately I haven’t fixed it yet. My Raspi has this IP: 192.168.179.65

I’ve set up the local dns server to the raspberry IP. There is only one option in the FritzBox Settings.

I was able to see the Toniebox in the Pi-Hole Dashboard.

I did a fresh Raspi OS Setup and started with this guide and installed everything fine. After that I installed Pi-Hole but now have problems because of the conflicting Port 80’s from teddycloud and Pi-Hole and I cannot access the Pi-Hole Dashboard at all. Ads are blocked on my mobile now, though.

Also, I am not able to access the teddycloud webview with port 8443 from my phone, but it works from the raspberry chromium.

I’m honestly sorry to bother you all with that network stuff… I just want to make it work :sweat_smile:

Edit: The “diff” command didn’t gave me any output at all.I guess that means the certs in the modified firmware and teddycloud are the same?

@Quoc Hey inonoob here, I helped Marco79cgn to flash his box.

If I see correctly you have a TTL to USB module. I think that won’t work. You need the CH341A as it uses the SPI protocol. The CH341A can be put into TTL to USB mode by removing the bridge.

I highly doubt that your module will work. But I might be wrong.

Best Regards

PS: I usually use the TTL to USB to connect to the raspberry pi serial port.

1 Like

@Martin_Gubin,

Did you set in the Fritzbox under Internet the DNS server or under Lokal Network ?

The one option in DNS server under Internet will take all request from the client to your Fritzbox ip and send the dns request to your Pi-hole. BUT your pi-hole will see all the request coming from the fritzbox. If you want that each client in your network has the Pi-hole as DNS entry you need to edit it in the network part and define “LOKALER DNS”

@Martin_Gubin

Quick question is your Pi-hole on the pi directly installed on also running on docker ?

I would suggest to have Pi-hole & Teddycloud running in docker and adapte the port of Pihole . Issue here Pi-hole docker is not the best. If you can, take a look at adguard it is way easier comparing to pi-hole.