Kirk: Difference between revisions

From PSP Developer wiki
Jump to navigation Jump to search
mNo edit summary
(22 intermediate revisions by the same user not shown)
Line 1: Line 1:
The PSP KIRK Crypto Engine is a security hardware device that is embedded into the TACHYON main IC chip. It is a bus master and can DMA to/from main DDR RAM memory, operating independantly of the CPU. It is intefaced via memory mapped registers at base of 0xBDE00000 ([[SPOCK Crypto Engine]] on the other hand is mapped to 0xBDF00000). It is capable of performing AES encryption, decryption, SHA1 Hash, pseudo random number generation, and signature generation and verifications (ECDSA) and CMAC.
The PSP KIRK Crypto Engine is a security hardware device that is embedded into the TACHYON main IC chip. It is a bus master and can DMA to/from main DDR RAM memory, operating independantly of the CPU. It is intefaced via memory mapped registers at base of 0xBDE00000 ([[SPOCK Crypto Engine]] on the other hand is mapped to 0xBDF00000). It is capable of performing AES encryption, decryption, SHA1 Hash, pseudo random number generation, and signature generation and verifications (ECDSA) and CMAC.
All (or almost all) the static keys used by the engine (plus the private key for KIRK CMD1) have been found through the PS3 hacks or glitching and can be found on the [[Keys]] page.
= Invocation =
All of the Kirk commands can be used using the function sceUtilsBufferCopyWithRange, which takes five arguments:
*the output buffer (if there is one, NULL otherwise)
*the output buffer size (if there is one, 0 otherwise)
*the input buffer (if there is one, NULL otherwise)
*the input buffer size (if there is one, 0 otherwise)
*the index of the command (as detailed below).
= Elliptic curves =
The PSP uses ECDSA for public-key cryptography. Elliptic curves are known for being fast and only requiring small keys, contrary to other public-key cryptography algorithms. They are still considered to be very secure, even for the 160-bit curves used by the PSP, unless a mistake is made when using them.
These curves have been designed by Sony only for the console. They are not vulnerable to any known attack.
Both use the usual Weierstrass form.
== Elliptic curve for CMD1 ==
This curve is used for the ECDSA verification of CMD1.
<pre>
p = 0xFFFFFFFFFFFFFFFF0001B5C617F290EAE1DBAD8F
G = (0x2259ACEE15489CB096A882F0AE1CF9FD8EE5F8FA, 0x604358456D0A1CB2908DE90F27D75C82BEC108C0)
n = 0xFFFFFFFFFFFFFFFF00000001FFFFFFFFFFFFFFFF
a = -3
b = 0x65D1488C0359E234ADC95BD3908014BD91A525F9
</pre>
The public key is hardcoded, and is equal to: (0xED9CE58234E61A53C685D64D51D0236BC3B5D4B9, 0x049DF1A075C0E04FB344858B61B79B69A63D2C39).
== Elliptic curve for the other commands ==
This curved is used for Kirk commands 0xC, 0xD, 0x10, 0x11, and likely 0x12.
<pre>
p = 0xFFFFFFFFFFFFFFFEFFFFB5AE3C523E63944F2127
G = (0x128EC4256487FD8FDF64E2437BC0A1F6D5AFDE2C, 0x5958557EB1DB001260425524DBC379D5AC5F4ADF)
n = 0xFFFFFFFFFFFFFFFF00000001FFFFFFFFFFFFFFFF
a = -3
b = 0xA68BEDC33418029C1D3CE33B9A321FCCBB9E0F0B
</pre>
The public key is variable. For the latest Pre-IPL version which add an additional ECDSA verification of the XOR of the block hashes, the public key is (0xBC660611A70BD7F2D140A48215C096D11D2D4112, 0xF0E9379AC4E0D387C542D091349DD15169DD5A87).
== Code sample ==
Below is an example of how to manipulate these curves using the ecpy python library.
<pre>
import ecpy.curves
psp_curve_cmd1 = {
    'name':      "psp_curve_cmd1",
    'type':      "weierstrass",
    'size':      160,
    'field':    0xFFFFFFFFFFFFFFFF00000001FFFFFFFFFFFFFFFF,
    'generator': (0x2259ACEE15489CB096A882F0AE1CF9FD8EE5F8FA, 0x604358456D0A1CB2908DE90F27D75C82BEC108C0),
    'order':    0xFFFFFFFFFFFFFFFF0001B5C617F290EAE1DBAD8F,
    'cofactor':  1,
    'a':        -3,
    'b':        0x65D1488C0359E234ADC95BD3908014BD91A525F9,
}
psp_curve_cmd17 = {
    'name':      "psp_curve_cmd17",
    'type':      "weierstrass",
    'size':      160,
    'field':    0xFFFFFFFFFFFFFFFF00000001FFFFFFFFFFFFFFFF,
    'generator': (0x128EC4256487FD8FDF64E2437BC0A1F6D5AFDE2C, 0x5958557EB1DB001260425524DBC379D5AC5F4ADF),
    'order':    0xFFFFFFFFFFFFFFFEFFFFB5AE3C523E63944F2127,
    'cofactor':  1,
    'a':        -3,
    'b':        0xA68BEDC33418029C1D3CE33B9A321FCCBB9E0F0B,
}
crv1 = ecpy.curves.WeierstrassCurve(psp_curve_cmd1)
crv17 = ecpy.curves.WeierstrassCurve(psp_curve_cmd17)
pt1 = ecpy.curves.Point(0xED9CE58234E61A53C685D64D51D0236BC3B5D4B9, 0x049DF1A075C0E04FB344858B61B79B69A63D2C39, crv1)
pt17 = ecpy.curves.Point(0xbc660611a70bd7f2d140a48215c096d11d2d4112, 0xf0e9379ac4e0d387c542d091349dd15169dd5a87, crv17)
# verify the KIRK1 ECDSA private key
crv1_g = ecpy.curves.Point(0x2259ACEE15489CB096A882F0AE1CF9FD8EE5F8FA, 0x604358456D0A1CB2908DE90F27D75C82BEC108C0, crv1)
assert(crv1.mul_point(crv1.generator, 0xF392E26490B80FD889F2D9722C1F34D7274F983D) == pt1)
</pre>


= Commands =
= Commands =
Line 16: Line 105:
! scope="col"| Input size
! scope="col"| Input size
! scope="col"| Output size
! scope="col"| Output size
! scope="col"| Result
! scope="col"| Used in
! scope="col"| Used in
|-
|-
Line 22: Line 110:
| KIRK_CMD_DECRYPT_PRIVATE
| KIRK_CMD_DECRYPT_PRIVATE
| Super-Duper decryption (no inverse)
| Super-Duper decryption (no inverse)
| buf_size+0x40
| buf_size+0x90
| buf_size
| buf_size
|
| memlmd, mesg_led
| memlmd, mesg_led
|-
|-
| 2
| 2
| KIRK_CMD_2
| KIRK_CMD_DRM_ENCRYPT
| Encrypt Operation (inverse of cmd 3)
| Encrypt Operation (inverse of cmd 3)
|  
| ?
|  
| ?
|
|  
|  
|-
|-
| 3
| 3
| KIRK_CMD_3
| KIRK_CMD_DRM_DECRYPT
| Decrypt Operation (inverse of cmd 2)
| Decrypt Operation (inverse of cmd 2)
|  
| ?
|  
| ?
|
|  
|  
|-
|-
| 4
| 4
| KIRK_CMD_ENCRYPT_IV_0
| KIRK_CMD_ENCRYPT_STATIC
| Encrypt Operation (inverse of cmd 7) (IV=0)
| Encrypt Operation (inverse of cmd 7) (key=static)
| buf_size+0x14
| buf_size+0x14
| buf_size+0x14
| buf_size+0x14
|
| chnnlsv, memab
| chnnlsv, memab
|-
|-
| 5
| 5
| KIRK_CMD_ENCRYPT_IV_FUSE
| KIRK_CMD_ENCRYPT_PERCONSOLE
| Encrypt Operation (inverse of cmd 8) (IV=FuseID)
| Encrypt Operation (inverse of cmd 8) (key=per-console)
| buf_size+0x14
| buf_size+0x14
| buf_size+0x14
| buf_size+0x14
|
| chnnlsv, psheet since PSP FW 2.81 for PGD, ?openpsid for IDS Certificates?
| chnnlsv, psheet since PSP FW 2.81 for PGD, ?openpsid for IDS Certificates?
|-
|-
| 6
| 6
| KIRK_CMD_ENCRYPT_IV_USER
| KIRK_CMD_ENCRYPT_USER
| Encrypt Operation (inverse of cmd 9) (IV=UserDefined)
| Encrypt Operation (inverse of cmd 9) (key=user-defined)
|  
| ?
|  
| ?
|
|  
|  
|-
|-
| 7
| 7
| KIRK_CMD_DECRYPT_IV_0
| KIRK_CMD_DECRYPT_STATIC
| Decrypt Operation (inverse of cmd 4) (IV=0)
| Decrypt Operation (inverse of cmd 4) (key=static)
| buf_size+0x14
| buf_size+0x14
| buf_size+0x14
| buf_size+0x14
|
| memlmd, mesg_led,chnnlsv, memab
| memlmd, mesg_led,chnnlsv, memab
|-
|-
| 8
| 8
| KIRK_CMD_DECRYPT_IV_FUSE
| KIRK_CMD_DECRYPT_PERCONSOLE
| Decrypt Operation (inverse of cmd 5) (IV=FuseID)
| Decrypt Operation (inverse of cmd 5) (key=per-console)
| buf_size+0x14
| buf_size+0x14
| buf_size+0x14
| buf_size+0x14
|
| chnnlsv, psheet since PSP FW 2.81 for PGD
| chnnlsv, psheet since PSP FW 2.81 for PGD
|-
|-
| 9
| 9
| KIRK_CMD_DECRYPT_IV_USER
| KIRK_CMD_DECRYPT_USER
| Decrypt Operation (inverse of cmd 6) (IV=UserDefined)
| Decrypt Operation (inverse of cmd 6) (key=user-defined)
|  
| ?
|  
| ?
|
|  
|  
|-
|-
Line 94: Line 173:
| KIRK_CMD_PRIV_SIGVRY
| KIRK_CMD_PRIV_SIGVRY
| Private Signature Verify (checks for private SCE sig)
| Private Signature Verify (checks for private SCE sig)
|  
| buf_size+0x90
|  
| 0
|
|  
|  
|-
|-
Line 103: Line 181:
| SHA1 Hash
| SHA1 Hash
| buf_size >= 0x14
| buf_size >= 0x14
| ?0x14?
| 0x14
|
| memlmd, mesg_led, memab
| memlmd, mesg_led, memab
|-
|-
| 12 (0xC)
| 12 (0xC)
| KIRK_CMD_MUL1
| KIRK_CMD_ECDSA_GENKEY
| ECDSA Generate Keys
| ECDSA Generate Private/Public Key Pair
| 0
| 0
| 0x3C
| 0x3C
|
| memab
| memab
|-
|-
| 13 (0xD)
| 13 (0xD)
| KIRK_CMD_MUL2
| KIRK_CMD_ECDSA_MUL
| ECDSA Multiply Point
| ECDSA Multiply Point
| 0x3C
| 0x3C
| 0x3C
| 0x3C
|
|  
|  
|-
|-
Line 128: Line 203:
| 0
| 0
| 0x14
| 0x14
|
| mesg_led, chnnlsv, memab, semawm
| mesg_led, chnnlsv, memab, semawm
|-
|-
| 15 (0xF)
| 15 (0xF)
| KIRK_CMD_15
| KIRK_CMD_15
| (absolutely no idea – could be KIRK initialization)
| (absolutely no idea – could be KIRK initialization or PRNG reseeding)
|  
| 0
|  
| 0
|
| IPL
| IPL
|-
|-
Line 144: Line 217:
| 0x34
| 0x34
| 0x28
| 0x28
|
| memab
| memab
|-
|-
Line 152: Line 224:
| 0x64
| 0x64
| 0
| 0
|
| memab
| memab
|-
|-
Line 160: Line 231:
| 0xB8
| 0xB8
| 0
| 0
|
| openpsid, memab
| openpsid, memab
|}
|}
Line 168: Line 238:
=== Overview ===
=== Overview ===


There are two versions of this service: AES CMAC Verification, and ECDSA Verification. They use the header section of the input buffer slightly differently as follows.
This function is used to both decrypt and verify the signature of the IPL blocks.


=== AES CMAC Version ===
There are two versions of this service: AES CMAC Verification, and ECDSA Verification. They use the header section of the input buffer slightly differently.


'''Key Header Structure (Length 0x60)''':
In both cases, the total header length is 0x90. The first 0x60 bytes depend on the version. The last 0x30 bytes are the same in both cases:
*0x00-0x0F is decryption key (but stored encrypted with AES128, is not PLAINTEXT key)
*0x10-0x1F is CMAC key (but again, derived ver not plain)
*0x20-0x2F is header hash (CMAC)
*0x30-0x3F is data hash (CMAC)
*0x40-0x5F is 0


'''Metadata Header Structure (Length 0x30)''':
'''Metadata Header Structure (Length 0x30)''':
{| class="wikitable"
|-
! Address !! Size !! Description
|-
| 0x60  || 4    || Set to 1
|-
| 0x64  || 4    || 0 indicates AES CMAC version, 1 indicates ECDSA version
|-
| 0x68  || 4    || 0
|-
| 0x6C  || 4    || 0 for retail version and 0xFFFFFFFF for dev versions
|-
| 0x70  || 4    || Length of decrypted data
|-
| 0x74  || 4    || Length of the padding after the header and before the real data
|-
| 0x78  || 8    || 0
|}


*0x60-0x63 is set to 1 to indicate KIRK1 Verification
=== AES CMAC Version ===
*0x64-0x67 is 0 to indicate AES CMAC Version
 
*0x68-0x6B is 0
'''Key Header Structure (Length 0x60)''':
*0x6C-0x6F is 0 for retail versions and 0xFFFFFFFF for dev versions
{| class="wikitable"
*0x70-0x73 is length of decrypted data
|-
*0x74-0x77 is length of padding after Metadata header before real data starts
! Address !! Size !! Description
*0x78-0x8F is 0
|-
| 0x00 || 16 || Decryption key, encrypted with the KIRK1 AES master key
|-
| 0x10 || 16 || CMAC key, encrypted with the KIRK1 AES master key
|-
| 0x20 || 16 || Header hash (CMAC)
|-
| 0x30 || 16 || Data hash (CMAC)
|-
| 0x40 || 32 || 0
|}


==== Decryption process ====
==== Decryption process ====


The first 0x20 bytes of the Key Header is decrypted with the KIRK 1 Stored AES Key. This was allegedly discovered by Datel by decapping the chip and reversing engineering the algorithms and keys. This was also recovered through the failure in PS3 cryptography by decrypting the isolated module in the PSP emulator on the PS3.
The first 0x20 bytes of the Key Header are decrypted with the KIRK 1 Stored AES Key. This was allegedly discovered by Datel by decapping the chip and reversing engineering the algorithms and keys. This was also recovered through the failure in PS3 cryptography by decrypting the isolated module in the PSP emulator on the PS3.


The first two blocks (0x20 bytes at offset 0) are decrypted with the KIRK 1 AES Key. The first block is the AES Key used for decrypting the main data. The second block is used to decrypt the next two blocks (0x20 bytes at offset 0x20). These represent the Metadata Header CMAC and the Data CMAC. They are checked against the AES CMAC of the header section and the AES CMAC of the data section.
The first block is the AES Key used for decrypting the main data. The second block is used to decrypt the next two blocks (0x20 bytes at offset 0x20). These represent the Metadata Header CMAC and the Data CMAC. They are checked against the AES CMAC of the metadata header section and the AES CMAC of the whole data, from the metadata header section to the end of the data (including padding in-between).


=== ECDSA Version ===
=== ECDSA Version ===


'''Key Header Structure (Length 0x60)''':
'''Key Header Structure (Length 0x60)''':
*0x00-0x0F is decryption key (but stored encrypted with AES128, is not PLAINTEXT key)
{| class="wikitable"
*0x10-0x23 is header ECDSA sig r
|-
*0x24-0x37 is header ECDSA sig s
! Address !! Size !! Description
*0x38-0x4b is data ECDSA sig r
|-
*0x4c-0x5f is data ECDSA sig s
| 0x00 || 0x10 || Decryption key, encrypted with the KIRK1 AES master key
 
|-
'''Metadata Header Structure (Length 0x30)''':
| 0x10 || 0x14 || Header ECDSA signature r
 
|-
*0x60-0x63 is set to 1 to indicate KIRK1 Verification
| 0x24 || 0x14 || Header ECDSA signature s
*0x64-0x67 is set to 1 to indicate ECDSA version
|-
*0x68-0x6B is 0
| 0x38 || 0x14 || Data ECDSA signature r
*0x6C-0x6F is 0 for retail versions and 0xFFFFFFFF for dev versions
|-
*0x70-0x73 is length of decrypted data
| 0x4C || 0x14 || Data ECDSA signature s
*0x74-0x77 is length of padding after Metadata header before real data starts
|}
*0x78-0x8F is 0


==== Decryption process ====
==== Decryption process ====


The ECDSA version is slightly different. Only the first block (0x10 bytes) is decrypted with the Kirk 1 AES Key. It is used to decrypt the main data section just as in the AES CMAC version. Rather than a CMAC, the Metadata header is checked by SHA1 hashing its 0x30 bytes and checking the signature components through a ECDSA Verify call. The Data section is also checked via SHA1 of the entire data through a ECDSA Verify call.
The ECDSA version is slightly different. Only the first block (0x10 bytes) is decrypted with the Kirk 1 AES Key. It is used to decrypt the main data section just as in the AES CMAC version. Rather than a CMAC, the Metadata header is checked by SHA1 hashing its 0x30 bytes and checking the signature components through a ECDSA Verify call. The encrypted Data section is also checked via SHA1 of the entire data through a ECDSA Verify call.


The ECDSA curve parameters used for this ECDSA Verification are as follows.
The ECDSA curve parameters are indicated above.


p=FFFFFFFFFFFFFFFF00000001FFFFFFFFFFFFFFFF
== Commands 2 & 3: DRM encrypt & decrypt ==


NP=FFFFFFFFFFFFFFFF0001B5C617F290EAE1DBAD8F
These commands are mostly unknown.
In command 2, the input data passed to KIRK is first checked (presumably CMAC), then decrypted, and re-encrypted with the console unique private key.
Having that common key would allow legit creation of DRM BB install packages.


a=-3
Command 3 is the decryption counterpart of command 2.


b=65D1488C0359E234ADC95BD3908014BD91A525F9
== Commands 4~9: AES encrypt & decrypt ==


'''Base Point''':
All these commands do AES128-CBC encryption/decryption with an IV equal to 0.
Gx=2259ACEE15489CB096A882F0AE1CF9FD8EE5F8FA
- Commands 4 (encryption) and 7 (decryption) use a one of the 128 keys stored in the Kirk chip and available on the [[Keys]] page, index being given by the keyseed field (which must be between 0x00 and 0x7F)
Gy=604358456D0A1CB2908DE90F27D75C82BEC108C0
- Commands 5 (encryption) and 8 (decryption) use an unknown per-console key (it is unknown if it is derived from other data, or just stored as-is on the chip)
- Commands 6 (encryption) and 9 (decryption) use a key derived from the keyseed using an unknown key derivation function


'''Public Point''':
In all cases, data is prefixed with a 0x14-byte long header:
Px=ED9CE58234E61A53C685D64D51D0236BC3B5D4B9
{| class="wikitable"
Py=049DF1A075C0E04FB344858B61B79B69A63D2C39
|-
! Address !! Size !! Description
|-
| 0x00 || 4 || Mode: must be 4 for encryption, 5 for decryption
|-
| 0x04 || 8 || Unknown (0?)
|-
| 0x0C || 4 || Keyseed
|-
| 0x10 || 4 || Size of the following data
|}


== Command 2 (DRM encrypt) ==
== Command 10: AES CMAC verification ==


This command is mostly unknown.
This seems to be the AES CMAC verification of CMD1, and takes the same header as CMD1, the only difference is that no decryption is performed.
The input data passed to KIRK is first checked (presumably CMAC), then decrypted, and re-encrypted with the console unique private key.
Having that common key would allow legit creation of DRM BB install packages.


== Command 3 ==
See command 1 information for details.


== Command 4 ==
It could also possibly verify CMACs for commands 2 & 3, but that is unknown.


== Command 5 ==
== Command 11: SHA1 ==


== Command 6 ==
This command computes the SHA1 of the input. The input must be prefixed with a 4-byte header giving the length of the buffer. Output is 0x14-byte long.


== Command 7 ==
== Command 12: ECDSA key pair generation ==


== Command 8 ==
This command generates a random private key and computes the associated public key. See above for the parameters of the elliptic curve.


== Command 9 ==
This returns the following into the keypair buffer, of size 0x3C (each value is 0x14 bytes long):
*0x00 - randomly generated private key
*0x14 - Public Key point x value
*0x28 - Public Key point y value


== Command 10 ==
== Command 13: ECDSA point multiplication ==


== Command 11 ==
This command multiplies an elliptic curve point by a scalar. See above for the parameters of the elliptic curve.


== Command 12: ECDSA key pair generation ==
Input (size 0x3c):
*0x00 - scalar k
*0x14 - point x value P.x
*0x28 - point y value P.y


Elliptic Curve Math formula : <math>y^2 = x^3 +ax +b mod p</math> with NP points on the curve
Output (size 0x28):
*0x00 - point x value (kP).x
*0x14 - point y value (kP).y


p = FFFFFFFFFFFFFFFF00000001FFFFFFFFFFFFFFFF
The result is a new point(x and y are each 0x14 bytes long).


N= FFFFFFFFFFFFFFFEFFFFB5AE3C523E63944F2127
== Command 14: PRNG ==


a= -3
This function takes no input and generates random data of the given size (depending on the specified size of the output buffer).


b= A68BEDC33418029C1D3CE33B9A321FCCBB9E0F0B
== Command 15: init? ==


'''Base Point''':
This function takes no input and no output.


Gx= 128EC4256487FD8FDF64E2437BC0A1F6D5AFDE2C
It could be either a Kirk initialization, or a PRNG re-seeding.


Gy= 5958557EB1DB001260425524DBC379D5AC5F4ADF
== Command 16: ECDSA signature generation ==


'''Invocation''':
This command generates an ECDSA signature of a SHA1 hash (0x14 buffer) using an encrypted private key.


<pre>
Input is:
u8 keypair[0x3c]
*0x00: 0x20-byte long encrypted buffer containing the private key
sceUtilsBufferCopyWithRange(keypair,0x3c,0,0,0xC);
*0x20: the message hash.
</pre>


This returns the following into the keypair buffer (each value is 0x14 bytes long):
The output is a 0x28-byte long signature (r and s, both 0x14-byte long).
*0x00 - randomly generated private key
*0x14 - Public Key point x value
*0x28 - Public Key point y value


Basically function 0xC generates a random number < N and multiplies it to the base point G to get the new public key.
The private key buffer is encrypted with a device-specific encryption using the FuseID.


== Command 13: point multiplication ==
Here is the code of the decryption, thanks to Davee & Proxima. g_fuse90 and g_fuse94 are the two words composing the FuseID (present at the 0xBC100090 and 0xBC100094 hardware registers).
Output is 0x20-byte long, but the last 0xC bytes are ignored (and possibly always equal to zero) for the private key.


Elliptic Curve Math formula : <math>y^2 = x^3 +ax +b mod p</math> with NP points on the curve
<pre>
void decrypt_kirk16_private(u8 *dA_out, u8 *dA_enc)
  int i, k;
  kirk16_data keydata;
  u8 subkey_1[0x10], subkey_2[0x10];
  rijndael_ctx aes_ctx;
 
  keydata.fuseid[7] = g_fuse90 &0xFF;
  keydata.fuseid[6] = (g_fuse90>>8) &0xFF;
  keydata.fuseid[5] = (g_fuse90>>16) &0xFF;
  keydata.fuseid[4] = (g_fuse90>>24) &0xFF;
  keydata.fuseid[3] = g_fuse94 &0xFF;
  keydata.fuseid[2] = (g_fuse94>>8) &0xFF;
  keydata.fuseid[1] = (g_fuse94>>16) &0xFF;
  keydata.fuseid[0] = (g_fuse94>>24) &0xFF;
  /* set encryption key */
  rijndael_set_key(&aes_ctx, kirk16_key, 128);
 
  /* set the subkeys */
  for (i = 0; i < 0x10; i++)
  {
    /* set to the fuseid */
    subkey_2[i] = subkey_1[i] = keydata.fuseid[i % 8];
  }


p = FFFFFFFFFFFFFFFF00000001FFFFFFFFFFFFFFFF
  /* do aes crypto */
  for (i = 0; i < 3; i++)
  {
    /* encrypt + decrypt */
    rijndael_encrypt(&aes_ctx, subkey_1, subkey_1);
    rijndael_decrypt(&aes_ctx, subkey_2, subkey_2);
  }


NP= FFFFFFFFFFFFFFFEFFFFB5AE3C523E63944F2127
  /* set new key */
  rijndael_set_key(&aes_ctx, subkey_1, 128);


a= -3
  /* now lets make the key mesh */
  for (i = 0; i < 3; i++)
  {
    /* do encryption in group of 3 */
    for (k = 0; k < 3; k++)
    {
      /* crypto */
      rijndael_encrypt(&aes_ctx, subkey_2, subkey_2);
    }


b= A68BEDC33418029C1D3CE33B9A321FCCBB9E0F0B
    /* copy to out block */
    memcpy(&keydata.mesh[i * 0x10], subkey_2, 0x10);
  }


'''Base Point''':
  /* set the key to the mesh */
  rijndael_set_key(&aes_ctx, &keydata.mesh[0x20], 128);


Gx= 128EC4256487FD8FDF64E2437BC0A1F6D5AFDE2C
  /* do the encryption routines for the aes key */
  for (i = 0; i < 2; i++)
  {
    /* encrypt the data */
    rijndael_encrypt(&aes_ctx, &keydata.mesh[0x10], &keydata.mesh[0x10]);
  }


Gy= 5958557EB1DB001260425524DBC379D5AC5F4ADF
  /* set the key to that mesh shit */
  rijndael_set_key(&aes_ctx, &keydata.mesh[0x10], 128);


'''Invocation''':
  /* cbc decrypt the dA */
 
  AES_cbc_decrypt((AES_ctx *)&aes_ctx, dA_enc, dA_out, 0x20);
<pre>
}
u8 buffer[0x3C]
u8 newpoint[0x28]
memcpy(buffer, multiplier, 0x14);
memcpy(buffer+0x14, pointx, 0x14);
memcpy(buffer+0x28, pointy, 0x14);
sceUtilsBufferCopyWithRange(newpoint,0x28,buffer,0x3c,0xD);
</pre>
</pre>


The result is a new point(x and y are each 0x14 bytes long).
== Command 17: ECDSA signature verification ==
 
To test this, you can call 0xC service and copy the first 0x14 bytes to a new buffer, then copy the Gx and Gy values after that. Calling 0xD with the new buffer will return the values of x and y that were generated by the 0xC call.


== Command 14 ==
This command verifies an ECDSA signature using the ECDSA curve described above.


== Command 15 ==
It takes no output, and takes as an input:
* 0x00: public key
* 0x28: signed message hash
* 0x3C: signature r
* 0x50: signature s


== Command 16 ==
The result of the operation is given by the return value (0 on success, 5 on failure to verify the signature).
 
== Command 17 ==


== Command 18 ==
== Command 18 ==


= Library =
Unknown.


== Calling commands using KIRK registers ==
= Code Samples =


* [https://github.com/DaveeFTW/iplsdk/tree/master/src/kirk]
* [https://github.com/DaveeFTW/iplsdk/tree/master/src/kirk]
Line 347: Line 498:
* [http://uofw.github.io/upspd/docs/SilverSpring_Blog/my.malloc.us/silverspring/kirk-crypto-engine/index.html]
* [http://uofw.github.io/upspd/docs/SilverSpring_Blog/my.malloc.us/silverspring/kirk-crypto-engine/index.html]


= Notes =
= Open problems =


In 2008 SilverSpring wrote:
* The private key corresponding to the latest version PRE-IPL public key is unknown.
<pre>
* Commands 2, 3, 5, 6, 8, 9 & 18 (and partly 10) are mostly unknown and need testing/documentation.
Currently what is known about the cipher is that it is:
a block cipher operating in CBC mode
an all zero 128-bit initialization vector
128-bit block and key sizes
cmd4/7 uses a static key that is identical in all PSP’s
cmd5/8 uses a key based off the fuseID making all operations unique per PSP
cmd6/9 uses a user-defined 128-bit key
cmd1/2/3 uses the block cipher but also signature algorithms
the remaining KIRK cmd’s do not use the block cipher (sig, hash, & prng algo’s)
</pre>

Revision as of 15:10, 4 February 2023

The PSP KIRK Crypto Engine is a security hardware device that is embedded into the TACHYON main IC chip. It is a bus master and can DMA to/from main DDR RAM memory, operating independantly of the CPU. It is intefaced via memory mapped registers at base of 0xBDE00000 (SPOCK Crypto Engine on the other hand is mapped to 0xBDF00000). It is capable of performing AES encryption, decryption, SHA1 Hash, pseudo random number generation, and signature generation and verifications (ECDSA) and CMAC.

All (or almost all) the static keys used by the engine (plus the private key for KIRK CMD1) have been found through the PS3 hacks or glitching and can be found on the Keys page.

Invocation

All of the Kirk commands can be used using the function sceUtilsBufferCopyWithRange, which takes five arguments:

  • the output buffer (if there is one, NULL otherwise)
  • the output buffer size (if there is one, 0 otherwise)
  • the input buffer (if there is one, NULL otherwise)
  • the input buffer size (if there is one, 0 otherwise)
  • the index of the command (as detailed below).

Elliptic curves

The PSP uses ECDSA for public-key cryptography. Elliptic curves are known for being fast and only requiring small keys, contrary to other public-key cryptography algorithms. They are still considered to be very secure, even for the 160-bit curves used by the PSP, unless a mistake is made when using them.

These curves have been designed by Sony only for the console. They are not vulnerable to any known attack.

Both use the usual Weierstrass form.

Elliptic curve for CMD1

This curve is used for the ECDSA verification of CMD1.

p = 0xFFFFFFFFFFFFFFFF0001B5C617F290EAE1DBAD8F
G = (0x2259ACEE15489CB096A882F0AE1CF9FD8EE5F8FA, 0x604358456D0A1CB2908DE90F27D75C82BEC108C0)
n = 0xFFFFFFFFFFFFFFFF00000001FFFFFFFFFFFFFFFF
a = -3
b = 0x65D1488C0359E234ADC95BD3908014BD91A525F9

The public key is hardcoded, and is equal to: (0xED9CE58234E61A53C685D64D51D0236BC3B5D4B9, 0x049DF1A075C0E04FB344858B61B79B69A63D2C39).

Elliptic curve for the other commands

This curved is used for Kirk commands 0xC, 0xD, 0x10, 0x11, and likely 0x12.

p = 0xFFFFFFFFFFFFFFFEFFFFB5AE3C523E63944F2127
G = (0x128EC4256487FD8FDF64E2437BC0A1F6D5AFDE2C, 0x5958557EB1DB001260425524DBC379D5AC5F4ADF)
n = 0xFFFFFFFFFFFFFFFF00000001FFFFFFFFFFFFFFFF
a = -3
b = 0xA68BEDC33418029C1D3CE33B9A321FCCBB9E0F0B

The public key is variable. For the latest Pre-IPL version which add an additional ECDSA verification of the XOR of the block hashes, the public key is (0xBC660611A70BD7F2D140A48215C096D11D2D4112, 0xF0E9379AC4E0D387C542D091349DD15169DD5A87).

Code sample

Below is an example of how to manipulate these curves using the ecpy python library.

import ecpy.curves

psp_curve_cmd1 = {
    'name':      "psp_curve_cmd1",
    'type':      "weierstrass",
    'size':      160,
    'field':     0xFFFFFFFFFFFFFFFF00000001FFFFFFFFFFFFFFFF,
    'generator': (0x2259ACEE15489CB096A882F0AE1CF9FD8EE5F8FA, 0x604358456D0A1CB2908DE90F27D75C82BEC108C0),
    'order':     0xFFFFFFFFFFFFFFFF0001B5C617F290EAE1DBAD8F,
    'cofactor':  1,
    'a':         -3,
    'b':         0x65D1488C0359E234ADC95BD3908014BD91A525F9,
}

psp_curve_cmd17 = {
    'name':      "psp_curve_cmd17",
    'type':      "weierstrass",
    'size':      160,
    'field':     0xFFFFFFFFFFFFFFFF00000001FFFFFFFFFFFFFFFF,
    'generator': (0x128EC4256487FD8FDF64E2437BC0A1F6D5AFDE2C, 0x5958557EB1DB001260425524DBC379D5AC5F4ADF),
    'order':     0xFFFFFFFFFFFFFFFEFFFFB5AE3C523E63944F2127,
    'cofactor':  1,
    'a':         -3,
    'b':         0xA68BEDC33418029C1D3CE33B9A321FCCBB9E0F0B,
}

crv1 = ecpy.curves.WeierstrassCurve(psp_curve_cmd1)
crv17 = ecpy.curves.WeierstrassCurve(psp_curve_cmd17)

pt1 = ecpy.curves.Point(0xED9CE58234E61A53C685D64D51D0236BC3B5D4B9, 0x049DF1A075C0E04FB344858B61B79B69A63D2C39, crv1)
pt17 = ecpy.curves.Point(0xbc660611a70bd7f2d140a48215c096d11d2d4112, 0xf0e9379ac4e0d387c542d091349dd15169dd5a87, crv17)

# verify the KIRK1 ECDSA private key
crv1_g = ecpy.curves.Point(0x2259ACEE15489CB096A882F0AE1CF9FD8EE5F8FA, 0x604358456D0A1CB2908DE90F27D75C82BEC108C0, crv1)
assert(crv1.mul_point(crv1.generator, 0xF392E26490B80FD889F2D9722C1F34D7274F983D) == pt1)

Commands

On PSP there are 18 KIRK commands. On PSVita, there are these 18 commands plus some new commands to support bigger keys (192 bits for example). See F00D commands.

KIRK functions are called with the same 5 arguments (outbuf, outbuf_size, inbuf, inbuf_size, service_number (which is the command ID)). Depending on the service number used, the expectations of the inbuf or outbuf vary and are detailed below.

Table

Command ID Name Short description Input size Output size Used in
1 KIRK_CMD_DECRYPT_PRIVATE Super-Duper decryption (no inverse) buf_size+0x90 buf_size memlmd, mesg_led
2 KIRK_CMD_DRM_ENCRYPT Encrypt Operation (inverse of cmd 3) ? ?
3 KIRK_CMD_DRM_DECRYPT Decrypt Operation (inverse of cmd 2) ? ?
4 KIRK_CMD_ENCRYPT_STATIC Encrypt Operation (inverse of cmd 7) (key=static) buf_size+0x14 buf_size+0x14 chnnlsv, memab
5 KIRK_CMD_ENCRYPT_PERCONSOLE Encrypt Operation (inverse of cmd 8) (key=per-console) buf_size+0x14 buf_size+0x14 chnnlsv, psheet since PSP FW 2.81 for PGD, ?openpsid for IDS Certificates?
6 KIRK_CMD_ENCRYPT_USER Encrypt Operation (inverse of cmd 9) (key=user-defined) ? ?
7 KIRK_CMD_DECRYPT_STATIC Decrypt Operation (inverse of cmd 4) (key=static) buf_size+0x14 buf_size+0x14 memlmd, mesg_led,chnnlsv, memab
8 KIRK_CMD_DECRYPT_PERCONSOLE Decrypt Operation (inverse of cmd 5) (key=per-console) buf_size+0x14 buf_size+0x14 chnnlsv, psheet since PSP FW 2.81 for PGD
9 KIRK_CMD_DECRYPT_USER Decrypt Operation (inverse of cmd 6) (key=user-defined) ? ?
10 (0xA) KIRK_CMD_PRIV_SIGVRY Private Signature Verify (checks for private SCE sig) buf_size+0x90 0
11 (0xB) KIRK_CMD_HASH SHA1 Hash buf_size >= 0x14 0x14 memlmd, mesg_led, memab
12 (0xC) KIRK_CMD_ECDSA_GENKEY ECDSA Generate Private/Public Key Pair 0 0x3C memab
13 (0xD) KIRK_CMD_ECDSA_MUL ECDSA Multiply Point 0x3C 0x3C
14 (0xE) KIRK_CMD_PRNGEN Pseudo Random Number Generation 0 0x14 mesg_led, chnnlsv, memab, semawm
15 (0xF) KIRK_CMD_15 (absolutely no idea – could be KIRK initialization or PRNG reseeding) 0 0 IPL
16 (0x10) KIRK_CMD_SIGGEN ECDSA Signature Generation 0x34 0x28 memab
17 (0x11) KIRK_CMD_SIGVRY Signature Verification (checks for generated signatures) 0x64 0 memab
18 (0x12) KIRK_CMD_CERTVRY Certificate Verification (IDStorage Certificates CMAC) 0xB8 0 openpsid, memab

Command 1: decryption and authentication

Overview

This function is used to both decrypt and verify the signature of the IPL blocks.

There are two versions of this service: AES CMAC Verification, and ECDSA Verification. They use the header section of the input buffer slightly differently.

In both cases, the total header length is 0x90. The first 0x60 bytes depend on the version. The last 0x30 bytes are the same in both cases:

Metadata Header Structure (Length 0x30):

Address Size Description
0x60 4 Set to 1
0x64 4 0 indicates AES CMAC version, 1 indicates ECDSA version
0x68 4 0
0x6C 4 0 for retail version and 0xFFFFFFFF for dev versions
0x70 4 Length of decrypted data
0x74 4 Length of the padding after the header and before the real data
0x78 8 0

AES CMAC Version

Key Header Structure (Length 0x60):

Address Size Description
0x00 16 Decryption key, encrypted with the KIRK1 AES master key
0x10 16 CMAC key, encrypted with the KIRK1 AES master key
0x20 16 Header hash (CMAC)
0x30 16 Data hash (CMAC)
0x40 32 0

Decryption process

The first 0x20 bytes of the Key Header are decrypted with the KIRK 1 Stored AES Key. This was allegedly discovered by Datel by decapping the chip and reversing engineering the algorithms and keys. This was also recovered through the failure in PS3 cryptography by decrypting the isolated module in the PSP emulator on the PS3.

The first block is the AES Key used for decrypting the main data. The second block is used to decrypt the next two blocks (0x20 bytes at offset 0x20). These represent the Metadata Header CMAC and the Data CMAC. They are checked against the AES CMAC of the metadata header section and the AES CMAC of the whole data, from the metadata header section to the end of the data (including padding in-between).

ECDSA Version

Key Header Structure (Length 0x60):

Address Size Description
0x00 0x10 Decryption key, encrypted with the KIRK1 AES master key
0x10 0x14 Header ECDSA signature r
0x24 0x14 Header ECDSA signature s
0x38 0x14 Data ECDSA signature r
0x4C 0x14 Data ECDSA signature s

Decryption process

The ECDSA version is slightly different. Only the first block (0x10 bytes) is decrypted with the Kirk 1 AES Key. It is used to decrypt the main data section just as in the AES CMAC version. Rather than a CMAC, the Metadata header is checked by SHA1 hashing its 0x30 bytes and checking the signature components through a ECDSA Verify call. The encrypted Data section is also checked via SHA1 of the entire data through a ECDSA Verify call.

The ECDSA curve parameters are indicated above.

Commands 2 & 3: DRM encrypt & decrypt

These commands are mostly unknown. In command 2, the input data passed to KIRK is first checked (presumably CMAC), then decrypted, and re-encrypted with the console unique private key. Having that common key would allow legit creation of DRM BB install packages.

Command 3 is the decryption counterpart of command 2.

Commands 4~9: AES encrypt & decrypt

All these commands do AES128-CBC encryption/decryption with an IV equal to 0. - Commands 4 (encryption) and 7 (decryption) use a one of the 128 keys stored in the Kirk chip and available on the Keys page, index being given by the keyseed field (which must be between 0x00 and 0x7F) - Commands 5 (encryption) and 8 (decryption) use an unknown per-console key (it is unknown if it is derived from other data, or just stored as-is on the chip) - Commands 6 (encryption) and 9 (decryption) use a key derived from the keyseed using an unknown key derivation function

In all cases, data is prefixed with a 0x14-byte long header:

Address Size Description
0x00 4 Mode: must be 4 for encryption, 5 for decryption
0x04 8 Unknown (0?)
0x0C 4 Keyseed
0x10 4 Size of the following data

Command 10: AES CMAC verification

This seems to be the AES CMAC verification of CMD1, and takes the same header as CMD1, the only difference is that no decryption is performed.

See command 1 information for details.

It could also possibly verify CMACs for commands 2 & 3, but that is unknown.

Command 11: SHA1

This command computes the SHA1 of the input. The input must be prefixed with a 4-byte header giving the length of the buffer. Output is 0x14-byte long.

Command 12: ECDSA key pair generation

This command generates a random private key and computes the associated public key. See above for the parameters of the elliptic curve.

This returns the following into the keypair buffer, of size 0x3C (each value is 0x14 bytes long):

  • 0x00 - randomly generated private key
  • 0x14 - Public Key point x value
  • 0x28 - Public Key point y value

Command 13: ECDSA point multiplication

This command multiplies an elliptic curve point by a scalar. See above for the parameters of the elliptic curve.

Input (size 0x3c):

  • 0x00 - scalar k
  • 0x14 - point x value P.x
  • 0x28 - point y value P.y

Output (size 0x28):

  • 0x00 - point x value (kP).x
  • 0x14 - point y value (kP).y

The result is a new point(x and y are each 0x14 bytes long).

Command 14: PRNG

This function takes no input and generates random data of the given size (depending on the specified size of the output buffer).

Command 15: init?

This function takes no input and no output.

It could be either a Kirk initialization, or a PRNG re-seeding.

Command 16: ECDSA signature generation

This command generates an ECDSA signature of a SHA1 hash (0x14 buffer) using an encrypted private key.

Input is:

  • 0x00: 0x20-byte long encrypted buffer containing the private key
  • 0x20: the message hash.

The output is a 0x28-byte long signature (r and s, both 0x14-byte long).

The private key buffer is encrypted with a device-specific encryption using the FuseID.

Here is the code of the decryption, thanks to Davee & Proxima. g_fuse90 and g_fuse94 are the two words composing the FuseID (present at the 0xBC100090 and 0xBC100094 hardware registers). Output is 0x20-byte long, but the last 0xC bytes are ignored (and possibly always equal to zero) for the private key.

void decrypt_kirk16_private(u8 *dA_out, u8 *dA_enc)
{   
  int i, k;
  kirk16_data keydata;
  u8 subkey_1[0x10], subkey_2[0x10];
  rijndael_ctx aes_ctx;
  
  keydata.fuseid[7] = g_fuse90 &0xFF;
  keydata.fuseid[6] = (g_fuse90>>8) &0xFF;
  keydata.fuseid[5] = (g_fuse90>>16) &0xFF;
  keydata.fuseid[4] = (g_fuse90>>24) &0xFF;
  keydata.fuseid[3] = g_fuse94 &0xFF;
  keydata.fuseid[2] = (g_fuse94>>8) &0xFF;
  keydata.fuseid[1] = (g_fuse94>>16) &0xFF;
  keydata.fuseid[0] = (g_fuse94>>24) &0xFF;
 
  /* set encryption key */
  rijndael_set_key(&aes_ctx, kirk16_key, 128);
  
  /* set the subkeys */
  for (i = 0; i < 0x10; i++)
  {
    /* set to the fuseid */
    subkey_2[i] = subkey_1[i] = keydata.fuseid[i % 8];
  } 

  /* do aes crypto */
  for (i = 0; i < 3; i++)
  {
    /* encrypt + decrypt */
    rijndael_encrypt(&aes_ctx, subkey_1, subkey_1);
    rijndael_decrypt(&aes_ctx, subkey_2, subkey_2);
  }

  /* set new key */
  rijndael_set_key(&aes_ctx, subkey_1, 128);

  /* now lets make the key mesh */
  for (i = 0; i < 3; i++)
  {
    /* do encryption in group of 3 */
    for (k = 0; k < 3; k++)
    {
      /* crypto */
      rijndael_encrypt(&aes_ctx, subkey_2, subkey_2);
    }

    /* copy to out block */
    memcpy(&keydata.mesh[i * 0x10], subkey_2, 0x10);
  }

  /* set the key to the mesh */
  rijndael_set_key(&aes_ctx, &keydata.mesh[0x20], 128);

  /* do the encryption routines for the aes key */
  for (i = 0; i < 2; i++)
  {
    /* encrypt the data */
    rijndael_encrypt(&aes_ctx, &keydata.mesh[0x10], &keydata.mesh[0x10]);
  }

  /* set the key to that mesh shit */
  rijndael_set_key(&aes_ctx, &keydata.mesh[0x10], 128);

  /* cbc decrypt the dA */
  AES_cbc_decrypt((AES_ctx *)&aes_ctx, dA_enc, dA_out, 0x20);
}

Command 17: ECDSA signature verification

This command verifies an ECDSA signature using the ECDSA curve described above.

It takes no output, and takes as an input:

  • 0x00: public key
  • 0x28: signed message hash
  • 0x3C: signature r
  • 0x50: signature s

The result of the operation is given by the return value (0 on success, 5 on failure to verify the signature).

Command 18

Unknown.

Code Samples

Open problems

  • The private key corresponding to the latest version PRE-IPL public key is unknown.
  • Commands 2, 3, 5, 6, 8, 9 & 18 (and partly 10) are mostly unknown and need testing/documentation.