Title Updates

From Vita Development Wiki
Revision as of 04:01, 15 September 2014 by Yifan Lu (talk | contribs) (Created page with 'Title update downloads are no longer as easy on on PS3. For PSVita title updates, the following path structure is used: <code><nowiki>https://gs-sec.ww.|NETWORK|.dl.playstati...')
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Title update downloads are no longer as easy on on PS3. For PSVita title updates, the following path structure is used:

https://gs-sec.ww.|NETWORK|.dl.playstation.net/pl/np/|TITLEID|/|HASH|/|TITLEID|-ver.xml

  • NETWORK can be np, sp-int, prod-qa, rc, or e1-np.
  • TITLEID is the title of the app. PCSA00007 for example.
  • HASH is a secret calculated hash based on the below algorithm:


int main(void) {
        char network[0x10];
        char title[0x10];
        // Secret HMAC key found in shell.self
        unsigned char key[0x20] = {0x9A, 0x9D, 0x07, 0xD5, 0x61, 0x9C, 0x3F, 0xFD, 0xDF, 0xF7, 0x58, 0xE3, 0xFC, 0x86, 0xC4, 0xB7,
                                   0x79, 0xFD, 0x63, 0x2D, 0x8D, 0xD4, 0x22, 0x54, 0x35, 0xC2, 0xE6, 0x2B, 0x2F, 0x4A, 0x2E, 0x6B };
        char uniqdata[0x20];
        int i,res;
        unsigned char result[0x20];
        memset(network,0,0x10);
        memset(uniqdata,0,0x20);
        memset(result,0,0x20);
        memset(title,0,0x10);
        printf("Enter network name (np, prod-qa, sp-int, rc, e1-np):"); scanf_s("%s", network,0x10);
        printf("Enter title id name (PCSA00000):"); scanf_s("%s", title,0x10);
        sprintf_s(uniqdata,0x20,"%s_%s", network,title );
        // Lovely obfuscation
        for(i=0;i<0x20;i++) key[i] ^= 0x7f;
        hmac_sha256(key,0x20,uniqdata,strlen(uniqdata),result);
        printf("https://gs-sec.ww.%s.dl.playstation.net/pl/%s/%s/", network,network,title);
        for(i=0;i<0x20;i++) {<
                printf("%02x", result[i]);
        }
        printf("/%s-ver.xml
", title);
        //printf("%s
", orig);
        return 0;
}

The hmac_sha256 function is not normal either. The made a couple of error or tweaks so it was not standard. Below is their hmac_sha256 function.


/**
 * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
 * @key: Key for HMAC operations
 * @key_len: Length of the key in bytes
 * @num_elem: Number of elements in the data vector
 * @addr: Pointers to the data areas
 * @len: Lengths of the data blocks
 * @mac: Buffer for the hash (32 bytes)
 */
void hmac_sha256_vector( u8 *key, size_t key_len, size_t num_elem,
             u8 *addr[],  size_t *len, u8 *mac)
{
    unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
    unsigned char tk[32];
     u8 *_addr[6];
    size_t _len[6], i;
    if (num_elem > 5) {
        /*
         * Fixed limit on the number of fragments to avoid having to
         * allocate memory (which could fail).
         */
        return;
    }
        /* if key is longer than 64 bytes reset it to key = SHA256(key) */
        if (key_len > 64) {
        sha256_vector(1, &key, &key_len, tk);
        key = tk;
        key_len = 32;
        }
    /* the HMAC_SHA256 transform looks like:
     *
     * SHA256(K XOR opad, SHA256(K XOR ipad, text))
     *
     * where K is an n byte key
     * ipad is the byte 0x36 repeated 64 times
     * opad is the byte 0x5c repeated 64 times
     * and text is the data being protected */
    /* start out by storing key in ipad */
    memset(k_pad, 0, sizeof(k_pad));
    memcpy(k_pad, key, key_len);
    /* XOR key with ipad values */
    for (i = 0; i < 64; i++)
        k_pad[i] ^= 0x36;

    /* perform inner SHA256 */
    _addr[0] = k_pad;
    _len[0] = 64;
    for (i = 0; i < num_elem; i++) {
        _addr[i + 1] = addr[i];
        _len[i + 1] = len[i];
    }
    sha256_vector(1 + num_elem, _addr, _len, mac);
		// NOTE: SCE HACK - they removed the clearing of the pad in their version.
    //memset(k_pad, 0, sizeof(k_pad));
    //memcpy(k_pad, key, key_len);
    /* XOR key with opad values */
    for (i = 0; i < 64; i++)
    		// NOTE: SCE HACK - they changed the normal 0x5C value to 0x6A
        k_pad[i] ^= 0x6A;
    /* perform outer SHA256 */
    _addr[0] = k_pad;
    _len[0] = 64;
    _addr[1] = mac;
    _len[1] = SHA256_MAC_LEN;
    sha256_vector(2, _addr, _len, mac);
}