DeviceSal Dict 000 (EKB) -> (status): Verify EKB file. For version 1, check SHA-1 of first 176 bytes. For any other, call DeviceSal Dict 159. Returns 0 if OK, otherwise an error code.
DeviceSal Dict 001
DeviceSal Dict 002
DeviceSal Dict 003
DeviceSal Dict 159 (EKB) -> (status): Verify EKB file with version > 1. Checks ECC signature, returns 0 if OK, otherwise an error code.
DeviceSal Dict 160
DeviceSal Dict 165
DeviceSal Dict 170
DeviceSal Dict 171
DeviceSal Dict 172: Dispatch table for D171.
DeviceSal Dict 173
DeviceSal Dict 174
DeviceSal Dict 175
DeviceSal Dict 177
DeviceSal Dict 178: Dispatch table for D177.
DeviceSal Dict 180 (a,b,c) -> (1): Returns 1.
DeviceSal Dict 181 (deskey,plain,cipher,xorout,xorin) -> (): DES-ECB-Encrypt "plain XORrep xorin" and set cipher to "that XORrep xorout".
DeviceSal Dict 182
DeviceSal Dict 183
DeviceSal Dict 184 (msg,tripdeskey) -> (mac): tripdeskey has two keys (2*8 bytes), say k1 ++ k2. DES-CBC-Encrypt msg with k1, then DES-Decrypt the last block with k2, DES-Encrypt that with k1, and return the single block result.
DeviceSal Dict 185 (cipher,iv,enckey2,encobj,key) -> (plain): DES-OCM-Decrypt encobj with "key", the plaintext is a 3DES key k1 ++ k2. DES-Decrypt enckey2 with k2, DES-Encrypt that with k1, resulting in key2. DES-CBC-Decrypt cipher with key2 and iv and return the result.
DeviceSal Dict 186 (plain,iv,encobj,key) -> (nkey,cipher): DES-OCM-Decrypt encobj with "key", the plaintext is a 3DES key k1 ++ k2. Then create a new key, and encrypt it with k2, that's nkey. Also encrypt the new key with k1, and use that to DES-CBC-Encrypt plain with iv into cipher.
DeviceSal Dict 187
DeviceSal Dict 189 (key,value) -> (): Use D191 as a map and enter (key, value) into it.
DeviceSal Dict 190 (key,default) -> (): Use D191 as map and return the value for key, or default if not found.
DeviceSal Dict 191: Variable to pass mapping to helper functions.
DeviceSal Dict 193
DeviceSal Dict 194
DeviceSal Dict 195
DeviceSal Dict 196
DeviceSal Dict 197: Dispatch table for 196.
DeviceSal Dict 198: (Decrypto with hook D249, reencrypt with DES-OCM)
DeviceSal Dict 199
DeviceSal Dict 207 (encobj, objkey) -> (...): DES-OCM-Decrypt encobj with objkey and unpack an ASN.1 encoded array (stripping off the length parameter)
DeviceSal Dict 208 (o1, o2, objkey) -> (encobj): DES-OCM-Encrypt an ASN.1 encoded array containing the first 8 bytes of o1 and o2 each.
DeviceSal Dict 209 (version) -> (ekbpath): Return the local EKB path.
DeviceSal Dict 210 () -> (1): Produce 1.
DeviceSal Dict 211
DeviceSal Dict 212
DeviceSal Dict 213
DeviceSal Dict 214 (encobj, protokey) -> (obj): Descramble cipher and OCM-Decrypt with SHA-1(protokey) and ASN.1-decode the result.
DeviceSal Dict 215 (obj, protokey) -> (encobj): OCM-Encrypt the serialized obj with SHA-1(protokey) and scramble the result.
DeviceSal Dict 216 (encobj, xorprotokey) -> (obj): DES-OCM-Decrypt with SHA-1(xorprotokey XOR D252++D252) and ASN.1-decode the result.
DeviceSal Dict 217 (obj, xorprotokey) -> (encobj): DES-OCM-Encrypt the serialized obj with SHA-1(xorprotokey XOR D252++D252).
DeviceSal Dict 220 (cipher, key) -> (plain): Decrypt with some weird SHA-1 based stream cipher.
DeviceSal Dict 221 (plain, key) -> (cipher): Encrypt with some weird SHA-1 based stream cipher.
Missing Info:
Dict 0xfc - contains an unknown 8 byte key, used in dev_0xd8, dev_0xd9.
Native modules:
// CBC Encrypt/Decrypt. The OUT buffer must be pre-allocated.
// Block size of the cipher is 64 bit, key length is 160 bit.
blob_t
native::ocmmod (blob_t in, blob_t out, blob_t key, int len, int decrypt)
{
if (decrypt)
ocmmod_cbc_decrypt (in, out, key, len);
else
ocmmod_cbc_encrypt (in, out, key, blob_len (in));
return out;
}
int
dev_0x01 (blob_t someblob, bool_t somebool)
{
int res;
if (somebool == 1)
{
res = dev_0x00 (someblob);
if (res != 0)
return res;
}
int some_nr = (unsigned) SubBlob (someblob, 0, 4);
int some_nr2 = (unsigned) dev_0xd1 (some_nr);
res = "localekb" (some_nr2);
// FIXME: Don't know the stack layout after this.
if (res != 0)
return; // but what?
blob_t someblob2; // probably from localekb
int some_nr3 = (signed) SubBlob (someblob2, 0, 4) + 1;
vector vec;
do
{
vec.append (SubBlob (some_nr3 * 16, 24));
}
while (some_nr3-- >= 0);
int some_nr3 = (signed) SubBlob (someblob2, 0, 4);
res = dev_0xc1 (some_nr3);
if (res != 0)
return res;
int some_nr4 = (signed) SubBlob (someblob2, 16, 4);
if (some_nr3 == some_nr4)
return 0;
else
return 8;
// is vec returned as well? it's still on the stack.
}
int
dev_0xb7 (any_t thing)
{
if (get_type (thing) != TYPE_BLOB)
return 0;
if (thing[2] == 0x31)
return 2;
else
{
if (! strncmp (thing, "\x31\x31", 2))
return 1;
else
return 0;
}
}
block_t
dev_0xd1 (int nr)
{
if (nr > 1)
{
0x80 ("Invalid version...");
return 0;
}
else
{
return 00 81 00 00 00 00 00 00;
}
}
// Some decrypt function.
// KEYBLOB seems to be 16 byte in practice.
any_t
dev_0xd8 (blob_t ciphertext, blob_t keyblob)
{
blob_t key = keyblob XOR concat (dict[0xfc], dict[0xfc]);
// Side-effect.
dict[0xdb] = key;
blob_t hashed_key = SHA1 (key[0..14]);
blob_t des_iv = hashed_key[0..7];
blob_t des_key = hashed_key[8..15]
blob_t data = DES_CBC_Decrypt (ciphertext, des_iv, des_key, 0xd8_DESDecrypt);
// Decrypt with ocmmod cipher.
int len = blob_length (data);
// Round up to multiple of 8.
len = (len + 7) / 8 * 8;
blob_t plaintext = repeat_nul (len);
plaintext = native::ocmmod (data, plaintext, hashed_key, len, 1);
// Return deserialized object.
return decode_asn1 (plaintext);
}
// Some encrypt function.
// KEYBLOB seems to be 16 byte in practice.
blob_t
dev_0xd9 (any_t plainobj, blob_t keyblob)
{
blob_t key = keyblob XOR concat (dict[0xfc], dict[0xfc]);
// Side-effect.
dict[0xdb] = key;
// Serialization.
plaintext = encode_asn1 (plaintext);
// Encrypt with ocmmod cipher.
int len = blob_length (data);
// Round up to multiple of 8.
len = (len + 7) / 8 * 8;
blob_t data = repeat_nul (len);
blob_t hashed_key = SHA1 (key[0..14]);
data = native::ocmmod (plaintext, data, hashed_key, len, 0);
// Encrypt DES.
blob_t des_iv = hashed_key[0..7];
blob_t des_key = hashed_key[8..15]
blob_t ciphertext = DES_CBC_Decrypt (data, des_iv, des_key, 0xd7_DESEncrypt);
return ciphertext;
}
NOT part of device.sal, but for lack of a better place, here an example of SsaTrans on updater.ocm:
$ SsaTrans updater.ocm
BCSeedRand63 (1, "j5\162\GS\140<,\f");
BCSetCryptTable ("L\225\164\152\DC1\RSD?\216f\198!\196\154\154\201\195b \192l^V\176r\245\151*\245[[\DC1\NULV#"...);
v_39 = BCNewBlob (8);
v_41 = BCDES_SetKey ("\188k\180(\150\EOT,\138");
arg_0 = Unknown
v_43 = BCDES_CBC BCDDecrypt (arg_0, v_39, v_41, "\216");
v_44 = BCBlobLength (v_43);
v_46 = BCBlobLength ("");
v_49 = BCSubBlob (v_43, v_44 - v_46, -1);
v_51 = BCCompareBlob (v_49, "");
if (v_51 == 0) [1 -> 1]
{
return [v_43, 1];
}
else [1 -> 1]
{
return [0];
}
v_56 = BCIfElse (v_43);
v_57 = BCSerialize (v_56);
return v_57;