2020-04-16 01:06:41 +01:00
/*
* Copyright ( c ) 2020 DarkMatterCore
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2020-04-11 06:28:26 +01:00
# pragma once
# ifndef __TIK_H__
# define __TIK_H__
2020-04-15 21:50:07 +01:00
# include <switch.h>
2020-04-11 06:28:26 +01:00
# include "signature.h"
2020-04-19 23:44:22 +01:00
# define TIK_MAX_SIZE 0x400 /* Max ticket entry size in the ES ticket system savedata file */
2020-04-29 22:11:27 +01:00
# define TIK_MIN_SIZE 0x1C0 /* Equivalent to sizeof(TikSigHmac160) - assuming no ESv2 records are available */
2020-04-11 06:28:26 +01:00
typedef enum {
2020-04-19 23:44:22 +01:00
TikType_None = 0 ,
TikType_SigRsa4096 = 1 ,
TikType_SigRsa2048 = 2 ,
2020-04-29 22:11:27 +01:00
TikType_SigEcc480 = 3 ,
TikType_SigHmac160 = 4
2020-04-11 06:28:26 +01:00
} TikType ;
typedef enum {
TikTitleKeyType_Common = 0 ,
2020-04-19 23:44:22 +01:00
TikTitleKeyType_Personalized = 1
2020-04-11 06:28:26 +01:00
} TikTitleKeyType ;
typedef enum {
TikLicenseType_Permanent = 0 ,
TikLicenseType_Demo = 1 ,
TikLicenseType_Trial = 2 ,
TikLicenseType_Rental = 3 ,
TikLicenseType_Subscription = 4 ,
TikLicenseType_Service = 5
} TikLicenseType ;
2020-05-01 16:06:24 +01:00
typedef enum {
TikPropertyMask_PreInstallation = BIT ( 0 ) ,
TikPropertyMask_SharedTitle = BIT ( 1 ) ,
TikPropertyMask_AllContents = BIT ( 2 ) ,
TikPropertyMask_DeviceLinkIndepedent = BIT ( 3 ) ,
TikPropertyMask_Volatile = BIT ( 4 ) ,
TikPropertyMask_ELicenseRequired = BIT ( 5 )
2020-04-11 06:28:26 +01:00
} TikPropertyMask ;
typedef enum {
TikSectionType_Permanent = 1 ,
TikSectionType_Subscription = 2 ,
TikSectionType_Content = 3 ,
TikSectionType_ContentConsumption = 4 ,
TikSectionType_AccessTitle = 5 ,
TikSectionType_LimitedResource = 6
} TikSectionType ;
/// Placed after the ticket signature block.
typedef struct {
2020-04-17 22:59:05 +01:00
u8 titlekey_block [ 0x100 ] ;
2020-04-11 06:28:26 +01:00
u8 format_version ;
2020-04-17 22:59:05 +01:00
u8 titlekey_type ; ///< TikTitleKeyType.
2020-04-11 06:28:26 +01:00
u16 ticket_version ;
u8 license_type ; ///< TikLicenseType.
u8 key_generation ;
2020-05-01 16:06:24 +01:00
u8 property_mask ; ///< TikPropertyMask.
2020-04-11 06:28:26 +01:00
u8 reserved_1 [ 0x9 ] ;
u64 ticket_id ;
u64 device_id ;
FsRightsId rights_id ;
u32 account_id ;
u32 sect_total_size ;
u32 sect_hdr_offset ;
u16 sect_hdr_count ;
u16 sect_hdr_entry_size ;
} TikCommonBlock ;
typedef struct {
2020-04-15 21:50:07 +01:00
SignatureBlockRsa4096 sig_block ;
2020-04-11 06:28:26 +01:00
TikCommonBlock tik_common_blk ;
} TikSigRsa4096 ;
typedef struct {
2020-04-15 21:50:07 +01:00
SignatureBlockRsa2048 sig_block ;
2020-04-11 06:28:26 +01:00
TikCommonBlock tik_common_blk ;
} TikSigRsa2048 ;
typedef struct {
2020-04-29 22:11:27 +01:00
SignatureBlockEcc480 sig_block ;
2020-04-11 06:28:26 +01:00
TikCommonBlock tik_common_blk ;
2020-04-29 22:11:27 +01:00
} TikSigEcc480 ;
typedef struct {
SignatureBlockHmac160 sig_block ;
TikCommonBlock tik_common_blk ;
} TikSigHmac160 ;
2020-04-11 06:28:26 +01:00
/// Section records are placed right after the ticket data. These aren't available in TikTitleKeyType_Common tickets.
/// These are only used if the sect_* fields are non-zero (other than 'sect_hdr_offset').
/// Each section record is followed by a 'record_count' number of Esv1 records, each one of 'record_size' size.
typedef struct {
u32 sect_offset ;
u32 record_size ;
u32 section_size ;
u16 record_count ;
u16 section_type ; ///< TikSectionType.
} TikEsv2SectionRecord ;
2020-04-17 22:59:05 +01:00
/// Used to store ticket type, size and raw data, as well as titlekey data.
2020-04-11 06:28:26 +01:00
typedef struct {
u8 type ; ///< TikType.
2020-04-17 22:59:05 +01:00
u64 size ; ///< Raw ticket size.
u8 data [ TIK_MAX_SIZE ] ; ///< Raw ticket data.
u8 enc_titlekey [ 0x10 ] ; ///< Titlekey with titlekek crypto (RSA-OAEP unwrapped if dealing with a TikTitleKeyType_Personalized ticket).
u8 dec_titlekey [ 0x10 ] ; ///< Titlekey without titlekek crypto. Ready to use for NCA FS section decryption.
2020-04-11 06:28:26 +01:00
} Ticket ;
2020-04-19 23:44:22 +01:00
/// Retrieves a ticket from either the ES ticket system savedata file (eMMC BIS System partition) or the secure hash FS partition from an inserted gamecard, using a Rights ID value.
2020-04-17 22:59:05 +01:00
/// Titlekey is also RSA-OAEP unwrapped (if needed) and titlekek decrypted right away.
bool tikRetrieveTicketByRightsId ( Ticket * dst , const FsRightsId * id , bool use_gamecard ) ;
2020-04-11 06:28:26 +01:00
2020-04-17 22:59:05 +01:00
/// Retrieves the common block from an input Ticket.
TikCommonBlock * tikGetCommonBlockFromTicket ( Ticket * tik ) ;
2020-04-11 06:28:26 +01:00
/// This will convert a TikTitleKeyType_Personalized ticket into a TikTitleKeyType_Common ticket.
/// Bear in mind the 'size' member from the Ticket parameter will be updated by this function to remove any possible references to TikEsv2SectionRecord records.
2020-04-17 22:59:05 +01:00
void tikConvertPersonalizedTicketToCommonTicket ( Ticket * tik ) ;
2020-04-11 06:28:26 +01:00
# endif /* __TIK_H__ */