Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tutorial] Manipulating the Puma7 itstore (truststore)
#1
On Puma7 modems (with secureboot), the certificates and other production related items are stored on a secure storage container called the itstore (or truststore).

The itstore encrypts the contents using a CPU specific key - so in general it is resistant to external attack (Phison mod, etc..).
In order to decrypt the contents of the truststore, the modem must be running and you must be able to execute code on the modem.

On most Puma7 modems, you can manipulate the truststore without any third-party applications/code simply by invoking the following commands from the ARM shell:

cli->co->system->ProductionSystem

createAsset [input] [target name] [islock=0/1]
readAsset [target] [output]
deleteAsset [target]

Even if these commands are removed by the MFG, you can access the itstore RPC server directly and request these via third-party code - as the modem itself must have this functionality to work - in short: this cannot be patched.

Dumping the itstore
To dump the certificates of a Puma7 modem, you can follow this example:
Code:
readAsset Doc31CmCert.bin /var/tmp/Doc31CmCert.bin
readAsset Doc31CmKey.bin /var/tmp/Doc31CmKey.bin
readAsset Doc31MfgCert.bin /var/tmp/Doc31MfgCert.bin
readAsset Doc31RootCert.bin /var/tmp/Doc31RootCert.bin
readAsset DocCmCert.bin /var/tmp/DocCmCert.bin
readAsset DocCmKey.bin /var/tmp/DocCmKey.bin
readAsset DocMfgCert.bin /var/tmp/DocMfgCert.bin
readAsset DocRootCert.bin /var/tmp/DocRootCert.bin
readAsset PcMfgCert.bin /var/tmp/PcMfgCert.bin
readAsset PcMtaCert.bin /var/tmp/PcMtaCert.bin
readAsset PcMtaKey.bin /var/tmp/PcMtaKey.bin
readAsset PcRootCert.bin /var/tmp/PcRootCert.bin
readAsset cablelabs_real_service_provider_root.cer /var/tmp/cablelabs_real_service_provider_root.cer
readAsset cablelabs_tst_service_provider_root.cer /var/tmp/cablelabs_tst_service_provider_root.cer
readAsset production.ini /var/tmp/production.ini
readAsset root_pub_key.bin /var/tmp/root_pub_key.bin
readAsset HWROB/HWROBDevCert.bin /var/tmp/HWROBDevCert.bin
readAsset HWROB/HWROBDevKey.bin /var/tmp/HWROBDevKey.bin
readAsset HWROB/HWROBRootCert.bin /var/tmp/HWROBRootCert.bin
readAsset HWROB/HWROBSubCaCert.bin /var/tmp/HWROBSubCaCert.bin

Then, you can encode each file as base64 and copy it out from your console (or transfer them via SFTP or some other technique).
This isn't required, but it's a convenient way to transfer the certificates if you only have a serial console available.

Code:
echo Doc31CmCert.bin:; base64 /var/tmp/Doc31CmCert.bin;echo Doc31CmKey.bin:; base64 /var/tmp/Doc31CmKey.bin;echo Doc31MfgCert.bin:; base64 /var/tmp/Doc31MfgCert.bin;echo Doc31RootCert.bin:; base64 /var/tmp/Doc31RootCert.bin;echo DocCmCert.bin:; base64 /var/tmp/DocCmCert.bin;echo DocCmKey.bin:; base64 /var/tmp/DocCmKey.bin;echo DocMfgCert.bin:; base64 /var/tmp/DocMfgCert.bin;echo DocRootCert.bin:; base64 /var/tmp/DocRootCert.bin;echo PcMfgCert.bin:; base64 /var/tmp/PcMfgCert.bin;echo PcMtaCert.bin:; base64 /var/tmp/PcMtaCert.bin;echo PcMtaKey.bin:; base64 /var/tmp/PcMtaKey.bin;echo PcRootCert.bin:; base64 /var/tmp/PcRootCert.bin;echo cablelabs_real_service_provider_root.cer:; base64 /var/tmp/cablelabs_real_service_provider_root.cer;echo cablelabs_tst_service_provider_root.cer:; base64 /var/tmp/cablelabs_tst_service_provider_root.cer;echo production.ini:; base64 /var/tmp/production.ini;echo root_pub_key.bin:; base64 /var/tmp/root_pub_key.bin
echo HWROBDevCert.bin:; base64 /var/tmp/HWROBDevCert.bin; echo HWROBDevKey.bin:; base64 /var/tmp/HWROBDevKey.bin;echo HWROBRootCert.bin:; base64 /var/tmp/HWROBRootCert.bin;echo HWROBSubCaCert.bin:; base64 /var/tmp/HWROBSubCaCert.bin;

I wrote a tool that takes the contents of those commands (base64'd files), and converts them to actual files for storage:


Code:
package main

import (
    "encoding/base64"
    "io/ioutil"
    "log"
    "os"
    "strings"
)

func main() {
    parseDump()
}

func parseDump(){
    fileBytes, _ := ioutil.ReadFile("dump.txt")
    sliceData := strings.Split(string(fileBytes), "\n")

    var filestarts []int
    
    for i, datum := range sliceData {
        if strings.Contains(datum, ":") {
            filestarts = append(filestarts, i)
        }
    }


    for i, filestart := range filestarts {
        start := filestart+1
        var end int
        if i == len(filestarts)-1 {
            end = len(sliceData)
        }else{
            end = filestarts[i+1]
        }

        //file := sliceData[start:end]
        file := sliceData[start:end]

        var b64 string
        for _, s := range file {
            b64 = b64 + strings.TrimSpace(s)
        }
        filename := strings.Split(strings.TrimSpace(sliceData[filestart]), ":")[0]
        log.Println(filename, b64)

        //fmt.Println("echo", b64, ">", filename+".b64")
        //fmt.Println("base64 -d", filename+".b64 > "+filename+"\n")

        //fmt.Println("createAsset /var/tmp/"+filename+" "+filename+" 0")

        dec, _ := base64.StdEncoding.DecodeString(b64)

        f, err := os.Create("output/"+filename)
        if err != nil {
            panic(err)
        }
        defer f.Close()

        if _, err := f.Write(dec); err != nil {
            panic(err)
        }
        if err := f.Sync(); err != nil {
            panic(err)
        }

    }
}

To use this, simply compile it, make a folder "output", then make a file "dump.txt", and paste the base64'd files from the above command in:
[Image: RmH2XUF.png]
It should look like this.
Run it, and you'll have all your certificates in plain text format in the output folder.

Modifying the itstore
To modify the itstore, you must first unlock the files (if they were created with islock=1 - which most MFGs do except for Hitron!)
You must do this from the Atom shell:

Code:
chattr -i itstore/*
chattr -i itstore/HWROB/*
chattr -i itstore/ssh/*
chattr -i itstore/.*
chattr -i itstore/HWROB/.*
chattr -i itstore/ssh/.*

If you cannot access the Atom shell, you can run the same commands from any Linux PC if you mount the device's NVRAM locally.

Then, you simply need to use createAsset to update the file.

For example if we want to change the modem's MAC, that is contained within production.ini, which looks something like this:

Code:
[macAddr]
cmdiag=00:00:00:00:00:00
ecm=00:00:00:00:00:00
emta=00:00:00:00:00:00
erouter0=00:00:00:00:00:00
erouter2=00:00:00:00:00:00
nsgmii0=00:00:00:00:00:00
nsgmii1=00:00:00:00:00:00
nsgmii2=00:00:00:00:00:00
nsgmii3=00:00:00:00:00:00
moca=00:00:00:00:00:00
ngmii4=00:00:00:00:00:00
ble=00:00:00:00:00:00
thread=00:00:00:00:00:00
zigbee=00:00:00:00:00:00

Once you have the file read (from readAsset), just edit the MAC, then use
Code:
createAsset /var/tmp/production.ini production.ini 0

to update the file in the itstore, successfully changing the MAC address of the modem.

Special thanks to Arrobazo & Flole
Reply
#2
that is some valuable info you just gave. muchly appreciated thanksĀ Arrobazo & Flole and BTC for all your hard work.

Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)