SSL services and Capture services: Difference between pages

From Nintendo Switch Brew
(Difference between pages)
Jump to navigation Jump to search
No edit summary
 
 
Line 1: Line 1:
= ssl =
= caps:a =
This is "nn::ssl::sf::ISslService". sdknso uses SessionManager with this, where the additional session-count is user-specified (default is 0x2). An error is thrown when the input value is less than 1 or >4.
This is "nn::capsrv::sf::IAlbumAccessorService".
 
This service implements client-mode TLS using [https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS NSS].
 
Note that SystemPrograms generally use [[#RegisterInternalPki]] (see [[libcurl]]). However, [[Internet_Browser|web-applets]] use [[#GetCertificates]] with [[#CaCertificateId]] All - [[#RegisterInternalPki]] is not used.


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 10: Line 6:
! Cmd || Name
! Cmd || Name
|-
|-
| 0 || [[#CreateContext]]
| 0 || GetAlbumFileCount
|-
| 1 || GetAlbumFileList
|-
| 2 || LoadAlbumFile
|-
| 3 || DeleteAlbumFile
|-
| 4 || StorageCopyAlbumFile
|-
| 5 || IsAlbumMounted
|-
|-
| 1 || [[#GetContextCount]]
| 6 || GetAlbumUsage
|-
|-
| 2 || [[#GetCertificates]]
| 7 || GetAlbumFileSize
|-
|-
| 3 || [[#GetCertificateBufSize]]
| 8 || LoadAlbumFileThumbnail
|-
|-
| 4 || [3.0.0+] [[#DebugIoctl]]
| 9 || [2.0.0+] LoadAlbumScreenShotImage
|-
|-
| 5 || [3.0.0+] [[#SetInterfaceVersion]]
| 10 || [2.0.0+] LoadAlbumScreenShotThumbnailImage
|-
|-
| 6 || [5.0.0+] [[#FlushSessionCache]]
| 11 || [2.0.0+] GetAlbumEntryFromApplicationAlbumEntry
|-
|-
| 7 || [6.0.0+] [[#SetDebugOption]]
| 12 || [3.0.0+] LoadAlbumScreenShotImageEx
|-
|-
| 8 || [6.0.0+] [[#GetDebugOption]]
| 13 || [3.0.0+] LoadAlbumScreenShotThumbnailImageEx
|-
| 14 || [3.0.0+] LoadAlbumScreenShotImageEx0
|-
| 15 || [4.0.0+] GetAlbumUsage3
|-
| 16 || [4.0.0+] GetAlbumMountResult
|-
| 17 || [4.0.0+] GetAlbumUsage16
|-
| 18 || [6.0.0+]
|-
| 100 || [5.0.0+] GetAlbumFileCountEx0
|-
| 101 || [5.0.0+] GetAlbumFileListEx0
|-
| 202 || [1.0.0-2.3.0] SaveEditedScreenShot
|-
| 301 || GetLastOverlayScreenShotThumbnail
|-
| 302 || [4.0.0+] GetLastOverlayMovieThumbnail
|-
| 401 || GetAutoSavingStorage
|-
| 501 || GetRequiredStorageSpaceSizeToCopyAll
|-
| 1001 || [3.0.0+] LoadAlbumScreenShotThumbnailImageEx0
|-
| 1002 || [3.0.0+] LoadAlbumScreenShotImageEx1
|-
| 1003 || [4.0.0+] LoadAlbumScreenShotThumbnailImageEx1
|-
| 8001 || ForceAlbumUnmounted
|-
| 8002 || ResetAlbumMountStatus
|-
| 8011 || RefreshAlbumCache
|-
| 8012 || GetAlbumCache
|-
| 8013 || [4.0.0+] GetAlbumCacheEx
|-
| 8021 || [2.0.0+] GetAlbumEntryFromApplicationAlbumEntryAruid
|-
| 10011 || SetInternalErrorConversionEnabled
|-
| 50000 || [6.0.0+] LoadMakerNoteInfoForDebug
|-
| 60002 || [4.0.0+] OpenAccessorSession
|}
|}


== CreateContext ==
Cmd18: Takes a type-70 buffer and returns a bool. If the buffer is sufficient it writes two application ID's to the buffer (0x100000000001000 and 0x100000000001fff) and returns true. This is used by photoViewer to group all screenshots of applets.
Takes a PID, an input u32 [[#SslVersion]], an input u64 pid_placeholder, and returns an output [[#ISslContext]].
 
== GetContextCount ==
No input, returns an output u32.
 
This is not exposed by sdknso.
 
== GetCertificates ==
Takes a type-0x6 output buffer and a type-0x5 input buffer containing an array of [[#CaCertificateId]].
 
[3.0.0+] This now returns an output u32 for actual total output entries.
 
The output buffer starts with an array of [[#BuiltInCertificateInfo]], with the DER cert data following afterwards.


== GetCertificateBufSize ==
Cmd1002: Takes a total of 0x38-bytes of input, two type-0x5 input buffers, and returns 0x20-bytes of output. [4.0.0+] No longer returns output, and now takes the following buffers instead: type-0x16, type-0x46, and type-0x6.
Takes a type-0x5 input buffer containing an array of [[#CaCertificateId]], returns an output u32 for the size to use with [[#GetCertificates]].


== DebugIoctl ==
Cmd60002: Takes a total of 8-bytes of input, a PID, and returns an [[#IAlbumAccessorSession]].
Stubbed on retail, just returns an error.


== SetInterfaceVersion ==
== IAlbumAccessorSession ==
Takes an input u32 '''version''', no output.
This is "nn::capsrv::sf::IAlbumAccessorSession".


Used by user-processes during service init.
This was added with [4.0.0+].


{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Value || SystemVersion
! Cmd || Name
|-
| 2001 || OpenAlbumMovieReadStream
|-
| 2002 || CloseAlbumMovieReadStream
|-
|-
| 0x1 || [3.0.0+]
| 2003 || GetAlbumMovieReadStreamMovieDataSize
|-
|-
| 0x2 || [5.0.0+]
| 2004 || ReadMovieDataFromAlbumMovieReadStream
|-
|-
| 0x3 || [6.0.0+]
| 2005 || GetAlbumMovieReadStreamBrokenReason
|-
| 2006 || GetAlbumMovieReadStreamImageDataSize
|-
| 2007 || ReadImageDataFromAlbumMovieReadStream
|-
| 2008 || ReadFileAttributeFromAlbumMovieReadStream
|}
|}


== FlushSessionCache ==
= caps:c =
Takes a type-0x5 input buffer, an input u32 [[#FlushSessionCacheOptionType]], returns an output u32.
This is "nn::capsrv::sf::IAlbumControlService", previously "nn::capsrv::sf::ICaptureControllerService" with [1.0.0].
 
The input buffer contains a NUL-terminated string, which is only used when the type is value 0. For type 1, an empty buffer is passed (addr=NULL/size=0).
 
== SetDebugOption ==
Takes an input u32 [[#DebugOptionType]] and a type-0x5 input buffer, no output.
 
The input u32 value must be 0, and the buffer addr/size must not be 0.
 
The u8 at buf+0 is copied to state.
 
The <code>nn::ssl::SetDebugOption</code> func in sdknso just verifies the input and that the service is initialized, without actually using the cmd.
 
== GetDebugOption ==
Takes an input u32 [[#DebugOptionType]] and a type-0x6 output buffer.
 
Same as [[#SetDebugOption]] except this copies state to the buffer instead.
 
== ISslContext ==
This is "nn::ssl::sf::ISslContext".


{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Cmd || Name
! Cmd || Name || Notes
|-
| [1.0.0] 1 || CaptureRawImage ||
|-
| [1.0.0] 2 || CaptureRawImageWithTimeout ||
|-
| 33 || [7.0.0+] ||
|-
| [1.0.0] 1001 || RequestTakingScreenShot ||
|-
| [1.0.0] 1002 || RequestTakingScreenShotWithTimeout ||
|-
| [1.0.0] 1011 || NotifyTakingScreenShotRefused ||
|-
| 2001 || NotifyAlbumStorageIsAvailable ||
|-
|-
| 0 || [[#SetOption]]
| 2002 || NotifyAlbumStorageIsUnavailable ||  
|-
|-
| 1 || [[#GetOption]]
| 2011 || [2.0.0+] RegisterAppletResourceUserId ||
|-
|-
| 2 || [[#CreateConnection]]
| 2012 || [2.0.0+] UnregisterAppletResourceUserId ||
|-
|-
| 3 || [[#GetConnectionCount]]
| 2013 || [2.0.0+] GetApplicationIdFromAruid ||
|-
|-
| 4 || [[#ImportServerPki]]
| 2014 || [2.0.0+] CheckApplicationIdRegistered ||
|-
|-
| 5 || [[#ImportClientPki]]
| 2101 || [2.0.0+] GenerateCurrentAlbumFileId || Takes an input u8 and u64, returns a 0x18-byte struct.
|-
|-
| 6 || [[#RemoveServerPki]]
| 2102 || [2.0.0+] GenerateApplicationAlbumEnrty ||
|-
|-
| 7 || [[#RemoveClientPki]]
| [2.0.0-3.0.2] 2201 || SaveAlbumScreenShotFile ||  
|-
|-
| 8 || [[#RegisterInternalPki]]
| 2202 || [4.0.0+] SaveAlbumScreenShotFileEx ||
|-
|-
| 9 || [[#AddPolicyOid]]
| 2301 || [2.0.0+] SetOverlayScreenShotThumbnailData ||
|-
|-
| 10 || [3.0.0+] [[#ImportCrl]]
| 2302 || [4.0.0+] SetOverlayMovieThumbnailData ||
|-
|-
| 11 || [3.0.0+] [[#RemoveCrl]]
| 60001 || [4.0.0+] OpenControlSession || Takes a total of 8-bytes of input and a PID, returns an [[#IAlbumControlSession]].
|}
|}


=== SetOption ===
=== Cmd33 ===
Takes an input [[#ContextOption]] and an input s32, no output.
Takes an input u64 [[#ShimLibraryVersion]], an u64 [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]], and a PID, no output.
 
With [[#ContextOption]] value 1, the s32 has to be 0 or 1 (state field is set to the s32 value).
 
Prior to 4.x this is stubbed.
 
=== GetOption ===
Takes an input [[#ContextOption]], returns an output s32.
 
Prior to 4.x this is stubbed.
 
=== CreateConnection ===
No input, returns an [[#ISslConnection]].
 
=== GetConnectionCount ===
No input, returns an output u32.


This is not exposed by sdknso. Immediately prior to closing the [[#ISslContext]] object, sdknso uses this cmd, returning the error from there on failure. An error is also thrown if the output count is non-zero.
This is used by [[Applet_Manager_services|caps:su]] SetShimLibraryVersion.


=== ImportServerPki ===
== IAlbumControlSession ==
Takes a type-0x5 input buffer and a [[#CertificateFormat]], returns an output u64 Id.
This is "nn::capsrv::sf::IAlbumControlSession".


The input buffer can contain multiple certs. A maximum of 71 ServerPki objects (associated with the output Id) can be imported.
This was added with [4.0.0+].
 
The certs can be CAs or server certs (no pubkeys).
 
=== ImportClientPki ===
Takes two type-0x5 input buffers, returns an output u64 Id.
 
The first buffer contains the PKCS#12 data, the second buffer contains the optional (addr=NULL/size=0) ASCII password. The password is copied to a heap buffer with size+1, for NUL-termination.
 
An error is thrown if this cmd or [[#RegisterInternalPki]] was already used previously.
 
=== RemoveServerPki ===
Takes an input u64 Id, no output.
 
=== RemoveClientPki ===
Takes an input u64 Id, no output.
 
=== RegisterInternalPki ===
Takes an input [[#InternalPki]], returns an output u64 Id.
 
An error is thrown if this cmd or [[#ImportClientPki]] was already used previously.
 
=== AddPolicyOid ===
Takes a type-0x5 input buffer, no output.
 
The buffer contains a string. The string length must not match the buffer size, and the string length must be <=0xFE.
 
=== ImportCrl ===
Takes a type-0x5 input buffer, returns an output u64 Id.
 
The input buffer contains the DER CRL.
 
=== RemoveCrl ===
Takes an input u64 Id, no output.
 
=== ISslConnection ===
This is "nn::ssl::sf::ISslConnection".


{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Cmd || Name
! Cmd || Name || Notes
|-
| 2001 || OpenAlbumMovieReadStream ||
|-
| 2002 || CloseAlbumMovieReadStream ||
|-
| 2003 || GetAlbumMovieReadStreamMovieDataSize ||
|-
| 2004 || ReadMovieDataFromAlbumMovieReadStream ||
|-
| 2005 || GetAlbumMovieReadStreamBrokenReason ||
|-
| 2006 || GetAlbumMovieReadStreamImageDataSize ||
|-
| 2007 || ReadImageDataFromAlbumMovieReadStream ||
|-
| 2008 || ReadFileAttributeFromAlbumMovieReadStream ||
|-
| 2401 || OpenAlbumMovieWriteStream ||
|-
| 2402 || FinishAlbumMovieWriteStream ||
|-
|-
| 0 || [[#SetSocketDescriptor]]
| 2403 || CommitAlbumMovieWriteStream ||  
|-
|-
| 1 || [[#SetHostName]]
| 2404 || DiscardAlbumMovieWriteStream ||  
|-
|-
| 2 || [[#SetVerifyOption]]
| 2405 || DiscardAlbumMovieWriteStreamNoDelete ||  
|-
|-
| 3 || [[#SetIoMode]]
| 2406 || [7.0.0+] CommitAlbumMovieWriteStreamEx ||
|-
|-
| 4 || [[#GetSocketDescriptor]]
| 2411 || StartAlbumMovieWriteStreamDataSection ||  
|-
|-
| 5 || [[#GetHostName]]
| 2412 || EndAlbumMovieWriteStreamDataSection ||  
|-
|-
| 6 || [[#GetVerifyOption]]
| 2413 || StartAlbumMovieWriteStreamMetaSection ||  
|-
|-
| 7 || [[#GetIoMode]]
| 2414 || EndAlbumMovieWriteStreamMetaSection ||  
|-
|-
| 8 || [[#DoHandshake]]
| 2421 || ReadDataFromAlbumMovieWriteStream ||  
|-
|-
| 9 || [[#DoHandshakeGetServerCert]]
| 2422 || WriteDataToAlbumMovieWriteStream ||  
|-
|-
| 10 || [[#Read]]
| 2424 || WriteMetaToAlbumMovieWriteStream ||  
|-
|-
| 11 || [[#Write]]
| 2431 || GetAlbumMovieWriteStreamBrokenReason ||  
|-
|-
| 12 || [[#Pending]]
| 2433 || GetAlbumMovieWriteStreamDataSize ||  
|-
|-
| 13 || [[#Peek]]
| 2434 || SetAlbumMovieWriteStreamDataSize ||
|}
 
= caps:u =
This is "nn::capsrv::sf::IAlbumApplicationService".
 
This was added with [5.0.0+].
 
Official sw via the <code>nn::album</code> wrappers uses start_DateTime = YYYY-MM-DD 1970-01-01 with the rest set to all-zero, end_DateTime is the same except year = 3000. With [[#GetAlbumFileList0AafeAruidDeprecated]], start_PosixTime = UTC 1999-12-31 00:00 (0x386BF200), and end_PosixTime = UTC 2100-01-01 00:00 (0xF4865700).
 
{| class="wikitable" border="1"
|-
|-
| 14 || [[#Poll]]
! Cmd || Name
|-
|-
| 15 || [[#GetVerifyCertError]]
| 32 || [7.0.0+] [[#SetShimLibraryVersion]]
|-
|-
| 16 || [[#GetNeededServerCertBufferSize]]
| 102 || [[#GetAlbumFileList0AafeAruidDeprecated]]
|-
|-
| 17 || [[#SetSessionCacheMode]]
| 103 || [[#DeleteAlbumFileByAruid]]
|-
|-
| 18 || [[#GetSessionCacheMode]]
| 104 || [[#GetAlbumFileSizeByAruid]]
|-
|-
| 19 || [[#FlushSessionCache]]
| 105 || [[#DeleteAlbumFileByAruidForDebug]]
|-
|-
| 20 || [[#SetRenegotiationMode]]
| 110 || [[#LoadAlbumScreenShotImageByAruid]]
|-
|-
| 21 || [[#GetRenegotiationMode]]
| 120 || [[#LoadAlbumScreenShotThumbnailImageByAruid]]
|-
|-
| 22 || [[#SetOption_2|SetOption]]
| 130 || [[#PrecheckToCreateContentsByAruid]]
|-
|-
| 23 || [[#GetOption_2|GetOption]]
| 140 || [6.0.0+] [[#GetAlbumFileList1AafeAruidDeprecated]]
|-
|-
| 24 || [[#GetVerifyCertErrors]]
| 141 || [6.0.0+] [[#GetAlbumFileList2AafeUidAruidDeprecated]]
|-
|-
| 25 || [4.0.0+] [[#GetCipherInfo]]
| 142 || [7.0.0+] [[#GetAlbumFileList3AaeAruid]]
|-
|-
| 26 || [9.0.0+] [[#SetNextAlpnProto]]
| 143 || [7.0.0+] [[#GetAlbumFileList4AaeUidAruid]]
|-
|-
| 27 || [9.0.0+] [[#GetNextAlpnProto]]
| 60002 || [[#OpenAccessorSessionForApplication]]
|}
|}


==== SetSocketDescriptor ====
== SetShimLibraryVersion ==
Takes an input s32 sockfd, returns an output s32 sockfd.
Takes an input u64 [[#ShimLibraryVersion]], an u64 [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]], and a PID, no output.


An error is thrown if this was used previously.
== GetAlbumFileList0AafeAruidDeprecated ==
Takes a type-0x6 output buffer containing an array of [[#ApplicationAlbumFileEntry]], a PID, an u8 [[#ContentType]], two s64s, and an u64 [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]]. Returns an output u64 for total output entries (which is copied to a s32 by official sw).


internal_sockfd = output from [[Sockets_services#DuplicateSocket|DuplicateSocket]], with the input sockfd. If the field which would be used for the input u64 (PID set by [[#CreateContext]]) is zero however, it instead uses internal_sockfd=input_sockfd directly without DuplicateSocket and later returns -1 for the sockfd. An error is thrown if DuplicateSocket fails. The input sockfd is later returned as the output sockfd, however if [[#OptionType|DoNotCloseSocket]] is set it will instead return -1 for the sockfd. Then [[Sockets_services#GetPeerName|GetPeerName]] is used with internal_sockfd, throwing an error if this fails. internal_sockfd is used for state initialization, and the input_sockfd is written into state.
The two s64s are the start/end PosixTime.


Immediately prior to closing the [[#ISslConnection]] object, sdknso will close the sockfd which was returned by this cmd if it is not negative.
== DeleteAlbumFileByAruid ==
Takes a PID, an input u8 [[#ContentType]], an [[#ApplicationAlbumFileEntry]], an [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]], and no output.


==== SetHostName ====
The [[#ContentType]] must match 3.
Takes a type-0x5 input buffer, no output.


The input buffer contains a string, the buffer size must be <=0xFF.
== GetAlbumFileSizeByAruid ==
Takes a PID, an input [[#ApplicationAlbumFileEntry]], an [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]], and returns an output u64.


The buffer is copied to a tmpbuf, then [[Sockets_services|nsd]] ResolveEx is used with this tmpbuf to set the HostName in state.
This gets the filesize for the entire specified Album file.


==== SetVerifyOption ====
== DeleteAlbumFileByAruidForDebug ==
Takes an input u32 [[#VerifyOption]], no output.
Takes a PID, an [[#ApplicationAlbumFileEntry]], an [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]], and no output.


==== SetIoMode ====
The cached value loaded from [[Settings_services#GetDebugModeFlag]] must be 1, otherwise an error is returned.
Takes an input [[#IoMode]], no output.


[[#SetSocketDescriptor]] must have been used prior to this successfully.
== LoadAlbumScreenShotImageByAruid ==
Takes a PID, a type-0x16 output buffer containing a [[#LoadAlbumScreenShotImageOutputForApplication]], a type-0x46 output buffer, a type-0x6 output buffer, an [[#ApplicationAlbumFileEntry]], a [[#ScreenShotDecodeOption]], and no output.


==== GetSocketDescriptor ====
The type-0x46 buffer contains the RGBA8 image data. The type-0x6 buffer is a work buffer used for reading the entire AlbumFile, the buffer size must be at least the AlbumFile filesize (cleared before the cmd returns).
No input, returns an output s32.


[[#SetSocketDescriptor]] must have been used prior to this successfully.
== LoadAlbumScreenShotThumbnailImageByAruid ==
Takes a PID, a type-0x16 output buffer containing a [[#LoadAlbumScreenShotImageOutputForApplication]], a type-0x46 output buffer,  a type-0x6 output buffer, an [[#ApplicationAlbumFileEntry]], a [[#ScreenShotDecodeOption]], and no output.


This gets the input_sockfd which was previously saved in state by [[#SetSocketDescriptor]].
The type-0x46 buffer contains the RGBA8 image data. The type-0x6 buffer is a work buffer used for reading the entire AlbumFile, the buffer size must be at least the AlbumFile filesize (cleared before the cmd returns).


==== GetHostName ====
== PrecheckToCreateContentsByAruid ==
Takes a type-0x6 output buffer, returns an output u32.
Takes a PID, an input u8 [[#ContentType]], an u64, an [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]], and no output.


The output u32 is the string length (buffer must be large enough for the entire string).
== GetAlbumFileList1AafeAruidDeprecated ==
Takes a type-0x6 output buffer containing an array of [[#ApplicationAlbumFileEntry]], a PID, an u8 [[#ContentType]], two [[#AlbumFileDateTime]], and an u64 [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]]. Returns an output u64 for total output entries (which is copied to a s32 by official sw).


==== GetVerifyOption ====
The first [[#AlbumFileDateTime]] is the start_DateTime, the second [[#AlbumFileDateTime]] is the end_DateTime. In the IPC rawdata, these use 2-byte alignment.
No input, returns an output u32 [[#VerifyOption]].


==== GetIoMode ====
== GetAlbumFileList2AafeUidAruidDeprecated ==
No input, returns an output [[#IoMode]].
Takes a type-0x6 output buffer containing an array of [[#ApplicationAlbumFileEntry]], a PID, an u8 [[#ContentType]], two [[#AlbumFileDateTime]], an u128 userID, and an u64 [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]]. Returns an output u64 for total output entries (which is copied to a s32 by official sw).


==== DoHandshake ====
The first [[#AlbumFileDateTime]] is the start_DateTime, the second [[#AlbumFileDateTime]] is the end_DateTime. In the IPC rawdata, these use 2-byte alignment.
No input/output.


[[#SetSocketDescriptor]] must have been used prior to this successfully.
== GetAlbumFileList3AaeAruid ==
Takes a type-0x6 output buffer containing an array of [[#ApplicationAlbumEntry]], a PID, an u8 [[#ContentType]], two [[#AlbumFileDateTime]], and an u64 [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]]. Returns an output u64 for total output entries (which is copied to a s32 by official sw).


The [[#SetHostName|hostname]] must be set (non-empty string) when [[#VerifyOption]] HostName is set, otherwise an error is thrown.
The first [[#AlbumFileDateTime]] is the start_DateTime, the second [[#AlbumFileDateTime]] is the end_DateTime. In the IPC rawdata, these use 2-byte alignment.


This will also set a callback eventually for saving an [[Error_Report_services|error-report]] when needed, which just contains the ErrorCode loaded from a Result in state. This sysmodule doesn't save any other reports elsewhere.
== GetAlbumFileList4AaeUidAruid ==
Takes a type-0x6 output buffer containing an array of [[#ApplicationAlbumEntry]], a PID, an u8 [[#ContentType]], two [[#AlbumFileDateTime]], an u128 userID, and an u64 [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]]. Returns an output u64 for total output entries (which is copied to a s32 by official sw).


==== DoHandshakeGetServerCert ====
The first [[#AlbumFileDateTime]] is the start_DateTime, the second [[#AlbumFileDateTime]] is the end_DateTime. In the IPC rawdata, these use 2-byte alignment.
Takes a type-0x6 output buffer, returns two output u32s.


Same as [[#DoHandshake]] except the params for the func called internally are user-specified, instead of all 0.
== OpenAccessorSessionForApplication ==
Takes a PID, an input [[#ApplicationAlbumFileEntry]], an u64 [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]], and returns an output [[#IAlbumAccessorApplicationSession]].


The buffer contains the output server cert DER. The first u32 is the output size, the second u32 is the total certs in the buffer.
== IAlbumAccessorApplicationSession ==
This is "nn::capsrv::sf::IAlbumAccessorApplicationSession".


When [[#OptionType|GetServerCertChain]] is set, the output buffer contains the full chain. This buffer can then be parsed by a seperate sdknso func:
This was added with [5.0.0+].
* The header is at +0. +0 must match a magicnum (0x4E4D684374726543 "CertChMN"), and the u32 at +0x4 must be larger than the input cert_index.
* The data at +0x10 is the 0x8-byte array-entries, for each cert. Entry +0x0 is the u32 size, and +0x4 is the u32 offset. These are copied to the output "nn::ssl::Connection::ServerCertDetail" struct, for the entry with the input cert_index: +0 = u32 size, +8 = address (input_buffer+offset).


No certs are returned when [[#VerifyOption|PeerCa]] is not set.
This is opened prior to using [[#OpenAlbumMovieReadStream]], when it previously wasn't opened. Official sw only closes this session when closing caps:u, not when using [[#CloseAlbumMovieReadStream]].


When [[#IoMode]] is NonBlocking the buffer will be only filled in once - when this cmd returns successfully the buffer will generally be empty.
{| class="wikitable" border="1"
 
|-
==== Read ====
! Cmd || Name
Takes a type-0x6 output buffer, returns an output u32.
|-
 
| 2001 || [[#OpenAlbumMovieReadStream]]
[[#SetSocketDescriptor]] must have been used prior to this successfully.
|-
 
| 2002 || [[#CloseAlbumMovieReadStream]]
The output u32 is the actual transferred size.
|-
 
| 2003 || [[#GetAlbumMovieReadStreamMovieDataSize]]
==== Write ====
|-
Takes a type-0x5 input buffer, returns an output u32.
| 2004 || [[#ReadMovieDataFromAlbumMovieReadStream]]
 
|-
[[#SetSocketDescriptor]] must have been used prior to this successfully.
| 2005 || [[#GetAlbumMovieReadStreamBrokenReason]]
|}


The output u32 is the actual transferred size.
=== OpenAlbumMovieReadStream ===
Takes a PID, an input [[#ApplicationAlbumFileEntry]], an u64 [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]], and returns an output u64 [[#AlbumMovieReadStreamHandle]].


==== Pending ====
Up to 4 streams can be open at the same time. Multiple streams can be open at the same time for the same [[#ApplicationAlbumFileEntry]].
No input, returns an output s32.


[[#SetSocketDescriptor]] must have been used prior to this successfully.
=== CloseAlbumMovieReadStream ===
Takes an input u64 [[#AlbumMovieReadStreamHandle]], no output.


==== Peek ====
=== GetAlbumMovieReadStreamMovieDataSize ===
Takes a type-0x6 output buffer, returns an output u32 size.
Takes an input u64 [[#AlbumMovieReadStreamHandle]], returns an output u64.


[[#SetSocketDescriptor]] must have been used prior to this successfully.
This gets the size of the actual MP4, without the JPEG at the end.


==== Poll ====
=== ReadMovieDataFromAlbumMovieReadStream ===
Takes an input [[#PollEvent]], an u32, returns an output [[#PollEvent]].
Takes a type-0x6 output buffer, an input u64 [[#AlbumMovieReadStreamHandle]], an input s64 offset, and returns an output u64 actual_size.


[[#SetSocketDescriptor]] must have been used prior to this successfully.
offset(+size) must not be negative. offset and size must be aligned to 0x40000-bytes. When offset(+size) goes beyond the size from [[#GetAlbumMovieReadStreamMovieDataSize]], the regions of the buffer which goes beyond that are cleared to 0, and actual_size is still set to the input size.


The u32 is the timeout in milliseconds.
=== GetAlbumMovieReadStreamBrokenReason ===
Takes an input u64 [[#AlbumMovieReadStreamHandle]], no output.


==== GetVerifyCertError ====
Unused by official sw.
No input/output.


This loads a field from state, clears the original value in state, and returns the Result from calling a conversion func with the loaded value.
= ShimLibraryVersion =
This is a version field. Official sw uses func <code>nn::capsrv::GetShimLibraryVersion()</code> to load this from a global var, which is then used with various commands (the input for those cmds must match value 1).


==== GetNeededServerCertBufferSize ====
[7.0.0-9.0.0] This is value 1.
No input, returns an output u32.


This just copies an u32 from state to output and returns 0.
Controls which struct version to use for [[#ApplicationAlbumEntry]] / [[#AlbumFileEntry]]. However, the struct size for the newer version is used regardless on [7.0.0+] for the actual cmds.


==== SetSessionCacheMode ====
= Enums =
Takes an input [[#SessionCacheMode]], no output.
 
[[#SetSocketDescriptor]] must have been used prior to this successfully.
 
==== GetSessionCacheMode ====
No input, returns an output [[#SessionCacheMode]].
 
[[#SetSocketDescriptor]] must have been used prior to this successfully.
 
==== FlushSessionCache ====
No input/output.
 
[[#SetSocketDescriptor]] must have been used prior to this successfully.
 
==== SetRenegotiationMode ====
Takes an input [[#RenegotiationMode]], no output.
 
[[#SetSocketDescriptor]] must have been used prior to this successfully.
 
==== GetRenegotiationMode ====
No input, returns an output [[#RenegotiationMode]].
 
[[#SetSocketDescriptor]] must have been used prior to this successfully.
 
==== SetOption ====
Takes an input u8 bool and an [[#OptionType]], no output.
 
==== GetOption ====
Takes an input [[#OptionType]], returns an output u8 bool.
 
==== GetVerifyCertErrors ====
Takes a type-0x6 output buffer, returns two output u32s.
 
On success, sdknso will throw an error if the two output u32s don't match.
 
==== GetCipherInfo ====
Takes an input u32 and a type-0x6 output buffer.
 
sdknso uses hard-coded value 0x1 for the u32. The output buffer contains [[#CipherInfo]].
 
Errors are thrown if the input u32 doesn't match 0x1, or if the buffer size doesn't match the size for [[#CipherInfo]].
 
[[#SetSocketDescriptor]] must have been used prior to this successfully.
 
==== SetNextAlpnProto ====
Takes a type-0x5 input buffer, no output.
 
[[#SetSocketDescriptor]] must have been used prior to this successfully.
 
The buffer size must be at least 0x2.
 
[[#OptionType|EnableAlpn]] should be set at the time of using DoHandshake*, otherwise using this cmd will have no affect.
 
The buffer contains an array of {u8 size, {data with the specified size}}, which must be within the buffer-size bounds.
 
==== GetNextAlpnProto ====
Takes a type-0x6 output buffer, returns an output [[#AlpnProtoState]] and an output u32.
 
[[#SetSocketDescriptor]] must have been used prior to this successfully.
 
The buffer contains the output string. The u32 is the output string length.
 
The output will be all-zero/empty if not available - such as when this was used before DoHandshake*.
 
= SslVersion =
This is "nn::ssl::sf::SslVersion" or "nn::ssl::Context::SslVersion". This is a bitmask which controls the min/max TLS versions to use, depending on which lowest/highest bits are set (if Auto isn't set). Auto uses min=1.0/max=1.2.


=== AlbumImageOrientation ===
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Bit
! Value
! Description
! Description
|-
|-
| 0 || Auto
| 0 || Unknown.
|-
|-
| 3 || TlsV10
| 1 || Unknown.
|-
|-
| 4 || TlsV11
| 2 || Unknown.
|-
|-
| 5 || TlsV12
| 3 || Unknown.
|}
|}


= DebugOptionType =
This is "nn::album::ImageOrientation".
This is "nn::ssl::sf::DebugOptionType" or "nn::ssl::DebugOption".


=== AlbumReportOption ===
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Value
! Value
! Description
! Description
|-
| 0 || Don't display the screenshot-taken Overlay-applet notification.
|-
|-
| 0 || AllowDisableVerifyOption
| 1 || Display the screenshot-taken Overlay notification.
|}
|}


= FlushSessionCacheOptionType =
This is "nn::album::AlbumReportOption".
This is "nn::ssl::sf::FlushSessionCacheOptionType" or "nn::ssl::FlushSessionCacheOptionType".


=== ContentType ===
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Value
! Value
! Description
! Description
|-
| 0 || Screenshot. Album screenshots.
|-
|-
| 0 || SingleHost
| 1 || Movie. Album videos.
|-
|-
| 1 || AllHosts
| 3 || ExtraMovie. Videos recorded by the current Application title via [[GRC_services#IMovieMaker|GRC MovieMaker]].
|}
|}


= BuiltInCertificateInfo =
=== AlbumStorage ===
This is "nn::ssl::BuiltInManager::BuiltInCertificateInfo".
 
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Offset
! Value
! Size
! Description
! Description
|-
|-
| 0x0
| 0 || Nand. ImageDirectory on the USER partition.
| 0x4
| [[#CaCertificateId]]
|-
|-
| 0x4
| 1 || Sd. ImageDirectory on the Sd card
| 0x4
| [[#TrustedCertStatus]]
|-
| 0x8
| 0x8
| CertificateSize
|-
| 0x10
| 0x8
| CertificateDataOffset
|}
|}


This is the struct returned by [[#GetCertificates]]. It is internally converted from "nn::ssl::detail::BuiltinDataInfo" by copying "nn::ssl::detail::BuiltinDataInfo::BuiltinDataStatus" into [[#TrustedCertStatus]] and official software then further converts this to "nn::ssl::BuiltInManager::BuiltInCertificateInfo" by transforming "CertificateDataOffset" into an actual pointer.
= AlbumFileDateTime =
 
= TrustedCertStatus =
This is "nn::ssl::TrustedCertStatus".
 
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Value
! Offset || Size || Description
! Description
|-
| 0x0 || 0x2 || Year
|-
| 0x2 || 0x1 || Month
|-
|-
| -1
| 0x3 || 0x1 || Day
| Invalid
|-
|-
| 0
| 0x4 || 0x1 || Hour
| Removed
|-
|-
| 1
| 0x5 || 0x1 || Minute
| EnabledTrusted
|-
|-
| 2
| 0x6 || 0x1 || Second
| EnabledNotTrusted
|-
|-
| 3
| 0x7 || 0x1 || Unique ID for when there's multiple Album files with the same timestamp.
| Revoked
|}
|}


= CaCertificateId =
This is "nn::capsrv::AlbumFileDateTime". This is a 0x8-byte struct.
This is "nn::ssl::CaCertificateId".


This corresponds to each field in the Album entry filename, prior to the "-": <code>YYYYMMDDHHMMSSII</code>.
= AlbumEntry =
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Value
! Offset || Size || Description
! Description
|-
|-
| -1 || [3.0.0+] All
| 0x0 || 0x8 || Size of the entry.
|-
|-
| 1 || NintendoCAG3
| 0x8 || 0x8 || ApplicationId
|-
|-
| 2 || NintendoClass2CAG3
| 0x10 || 0x8 || [[#AlbumFileDateTime]]
|-
|-
| 1000 || AmazonRootCA1
| 0x18 || 0x1 || [[#AlbumStorage]]
|-
|-
| 1001 || StarfieldServicesRootCertificateAuthorityG2
| 0x19 || 0x1 || [[#ContentType]]
|-
|-
| 1002 || AddTrustExternalCARoot
| 0x1A || 0x6 || Padding.
|-
|}
| 1003 || COMODOCertificationAuthority
 
|-
This is "nn::capsrv::AlbumEntry". This is a 0x20-byte struct.
| 1004 || UTNDATACorpSGC
 
|-
= AlbumFileEntry =
| 1005 || UTNUSERFirstHardware
This is "nn::album::AlbumFileEntry". This is identical to [[#ApplicationAlbumEntry]]. On older versions where official sw used to use cmds which use [[#ApplicationAlbumFileEntry]], this struct matches [[#ApplicationAlbumFileEntry]].
|-
 
| 1006 || BaltimoreCyberTrustRoot
= ApplicationAlbumEntry =
|-
{| class="wikitable" border="1"
| 1007 || CybertrustGlobalRoot
|-
| 1008 || VerizonGlobalRootCA
|-
| 1009 || DigiCertAssuredIDRootCA
|-
| 1010 || DigiCertAssuredIDRootG2
|-
| 1011 || DigiCertGlobalRootCA
|-
| 1012 || DigiCertGlobalRootG2
|-
| 1013 || DigiCertHighAssuranceEVRootCA
|-
| 1014 || EntrustnetCertificationAuthority2048
|-
| 1015 || EntrustRootCertificationAuthority
|-
| 1016 || EntrustRootCertificationAuthorityG2
|-
| 1017 || GeoTrustGlobalCA2 ([8.0.0+] [[#TrustedCertStatus]] is EnabledNotTrusted)
|-
|-
| 1018 || GeoTrustGlobalCA ([8.0.0+] [[#TrustedCertStatus]] is EnabledNotTrusted)
! Offset || Size || Description
|-
|-
| 1019 || GeoTrustPrimaryCertificationAuthorityG3 ([8.0.0+] [[#TrustedCertStatus]] is EnabledNotTrusted)
| 0x0 || 0x8 || Size of the entry.
|-
|-
| 1020 || GeoTrustPrimaryCertificationAuthority ([8.0.0+] [[#TrustedCertStatus]] is EnabledNotTrusted)
| 0x8 || 0x8 || AES256 with hardcoded key over AlbumEntry.  
|-
|-
| 1021 || GlobalSignRootCA
| 0x10 || 0x8 || [[#AlbumFileDateTime]]
|-
|-
| 1022 || GlobalSignRootCAR2
| 0x18 || 0x1 || [[#AlbumStorage]]
|-
|-
| 1023 || GlobalSignRootCAR3
| 0x19 || 0x1 || [[#ContentType]]
|-
|-
| 1024 || GoDaddyClass2CertificationAuthority
| 0x1a || 0x5 || Padding.
|-
|-
| 1025 || GoDaddyRootCertificateAuthorityG2
| 0x1f || 0x1 || Unknown. Set to 1 by official software.
|-
| 1026 || StarfieldClass2CertificationAuthority
|-
| 1027 || StarfieldRootCertificateAuthorityG2
|-
| 1028 || thawtePrimaryRootCAG3 ([8.0.0+] [[#TrustedCertStatus]] is EnabledNotTrusted)
|-
| 1029 || thawtePrimaryRootCA ([8.0.0+] [[#TrustedCertStatus]] is EnabledNotTrusted)
|-
| 1030 || VeriSignClass3PublicPrimaryCertificationAuthorityG3 ([8.0.0+] [[#TrustedCertStatus]] is EnabledNotTrusted)
|-
| 1031 || VeriSignClass3PublicPrimaryCertificationAuthorityG5 ([8.0.0+] [[#TrustedCertStatus]] is EnabledNotTrusted)
|-
| 1032 || VeriSignUniversalRootCertificationAuthority ([8.0.0+] [[#TrustedCertStatus]] is EnabledNotTrusted)
|-
| 1033 || [6.0.0+] DSTRootCAX3
|-
| 1034 || [10.0.3+] "USERTrust RSA Certification Authority"
|}
|}


= InternalPki =
This is "nn::capsrv::ApplicationAlbumEntry". This is a 0x20-byte struct. On older versions where [[#ShimLibraryVersion]] is 0, this was a plain AES256 with a random key generated at application launch.
This is "nn::ssl::sf::InternalPki" or "nn::ssl::Context::InternalPki".


With the output from [[Applet_Manager_services#caps:su|caps:su]] sdk-nso only uses this for the [[Internet_Browser|Share-applet]] (when the output is used at all), with everything else it's used as an [[#AlbumFileEntry]]. In those cases with the <code>nn::album</code> wrapper funcs, it's "converted" by just copying the struct (arrays are "converted" by just returning a ptr to the input array).
= ApplicationAlbumFileEntry =
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Value
! Offset || Size || Description
! Description
|-
| 0x0 || 0x20 || [[#ApplicationAlbumEntry]]
|-
|-
| 0 || None
| 0x20 || 0x8 || [[#AlbumFileDateTime]]
|-
|-
| 1 || DeviceClientCertDefault
| 0x28 || 0x8 || Unknown.
|}
|}


An error is thrown by [[#RegisterInternalPki]] when the input value does not match "DeviceClientCertDefault".
This is "nn::capsrv::ApplicationAlbumFileEntry". This is a 0x30-byte struct.
 
"DeviceClientCertDefault" enables using the DeviceCert.
 
= ContextOption =
This is "nn::ssl::sf::ContextOption" or "nn::ssl::Context::ContextOption".


The default value for CrlImportDateCheckEnable at the time of [[#ISslContext]] object creation is value 1.
On newer versions where official sw uses [[#ApplicationAlbumEntry]], [[#ApplicationAlbumEntry]] is converted to ApplicationAlbumFileEntry when using cmds which need it with:
* First 0x20-bytes are the same.
* u64 ApplicationAlbumFileEntry+0x20 = [[#ApplicationAlbumEntry]]+0x10.
* Last 8-bytes = 0.


= ScreenShotAttribute =
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Value
! Offset || Size || Description
! Description
|-
| 0x0 || 0x4 || Always set to 0 by official sw.
|-
|-
| 0 || None
| 0x4 || 0x4 || [[#AlbumImageOrientation]]
|-
|-
| 1 || CrlImportDateCheckEnable
| 0x8 || 0x4 || Always set to 0 by official sw.
|-
| 0xC || 0x4 || Always set to 1 by official sw.
|-
| 0x10 || 0x30 || Always set to 0 by official sw.
|}
|}


= CertificateFormat =
This is "nn::capsrv::detail::ScreenShotAttributeEx0" / "nn::capsrv::ScreenShotAttribute". This is a 0x40-byte struct.
This is "nn::ssl::sf::CertificateFormat" or "nn::ssl::CertificateFormat".


= ApplicationData =
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Value
! Offset || Size || Description
! Description
|-
|-
| 1 || Pem
| 0x0 || 0x400 || UserData
|-
|-
| 2 || Der
| 0x400 || 0x4 || UserData size.
|}
|}


= VerifyOption =
This is "nn::capsrv::ApplicationData". This is a 0x404-byte struct.
This is "nn::ssl::sf::VerifyOption". This is a bitmask. At the time of [[#ISslConnection]] object creation, the default value is 0x3.


= UserIdList =
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Bit
! Offset || Size || Description
! Description
|-
| 0 || PeerCa
|-
| 1 || HostName
|-
| 2 || DateCheck
|-
|-
| 3 || EvCertPartial
| 0x0 || 0x80 || u128 userIDs
|-
|-
| 4 || [6.0.0+] EvPolicyOid
| 0x80 || 0x1 || Total userIDs.
|-
|-
| 5 || [6.0.0+] EvCertFingerprint
| 0x81 || 0x7 || Padding.
|}
|}


Originally ssl-sysmodule ([[#SetVerifyOption]]) just wrote the input field to state. With [5.0.0+] there's now validation for the input, with the value written to state masked with {allowed bitmask}. When [[#SetInterfaceVersion|InterfaceVersion]] is >=0x2, the low 2-bits of VerifyOption must be set, unless {state flag for [[#OptionType|SkipDefaultVerify]]} is set or [9.0.0+] {bool [[#SetDebugOption|DebugOption]] state flag} is set, otherwise an error is thrown. [6.0.0+]: Following that, if VerifyOption bit4 is set, then VerifyOption & 0x15 must match 0x15 otherwise an error is thrown.
This is "nn::capsrv::UserIdList". This is a 0x88-byte struct.
 
= IoMode =
This is "nn::ssl::sf::IoMode" or "nn::ssl::Connection::IoMode". At the time of [[#ISslConnection]] object creation, the default value is 1.
 
The socket non-blocking flag is always set regardless of this field, this is only used for calculating the timeout (converted from milliseconds) passed to the NSS funcs used by various cmds. NonBlocking = 0, Blocking = 300000 (5 minutes).


= LoadAlbumScreenShotImageOutputForApplication =
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Value
! Offset || Size || Description
! Description
|-
|-
| 1 || Blocking
| 0x0 || 0x8 || s64 Width. Official sw copies this to a s32 output field.
|-
| 2 || NonBlocking
|}
 
= PollEvent =
This is "nn::ssl::sf::PollEvent" or "nn::ssl::Connection::PollEvent". This is a bitmask.
 
{| class="wikitable" border="1"
|-
|-
! Bit
| 0x8 || 0x8 || s64 Height. Official sw copies this to a s32 output field.
! Description
|-
|-
| 0 || Read
| 0x10 || 0x40 || [[#ScreenShotAttributeForApplication]]
|-
|-
| 1 || Write
| 0x50 || 0x404 || [[#ApplicationData]]
|-
|-
| 2 || Except
| 0x454 || 0xAC || Unused
|}
|}


= SessionCacheMode =
This is "nn::capsrv::sf::LoadAlbumScreenShotImageOutputForApplication". This is a 0x500-byte struct.
This is "nn::ssl::sf::SessionCacheMode" or "nn::ssl::Connection::SessionCacheMode".
 
= ScreenShotDecodeOption =
This is "nn::capsrv::ScreenShotDecodeOption". This is a 0x20-byte struct.
 
Official sw sets this to all-zero with the input for [[#LoadAlbumScreenShotImageByAruid]]/[[#LoadAlbumScreenShotThumbnailImageByAruid]].


= ScreenShotAttributeForApplication =
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Value
! Offset || Size || Description
! Description
|-
|-
| 0 || None
| 0x0 || 0x4 || Unknown.
|-
|-
| 1 || SessionId
| 0x4 || 0x1 || Unknown.
|-
| 2 || SessionTicket
|}
 
= RenegotiationMode =
This is "nn::ssl::sf::RenegotiationMode" or "nn::ssl::Connection::RenegotiationMode".
 
{| class="wikitable" border="1"
|-
|-
! Value
| 0x5 || 0x1 || Unknown.
! Description
|-
|-
| 0 || None
| 0x6 || 0x1 || Unknown.
|-
|-
| 1 || Secure
| 0x7 || 0x1 || Padding.
|}
 
= OptionType =
This is "nn::ssl::sf::OptionType" or "nn::ssl::Connection::OptionType".
 
{| class="wikitable" border="1"
|-
|-
! Value
| 0x8 || 0x4 || Unknown.
! Description
|-
|-
| 0 || DoNotCloseSocket
| 0xC || 0x4 || Unknown.
|-
|-
| 1 || [3.0.0+] GetServerCertChain
| 0x10 || 0x4 || Unknown.
|-
|-
| 2 || [5.0.0+] SkipDefaultVerify
| 0x14 || 0x4 || Unknown.
|-
|-
| 3 || [9.0.0+] EnableAlpn
| 0x18 || 0x4 || Unknown.
|}
 
This corresponds to bool flags. At the time of [[#ISslConnection]] object creation, all of these bool flags are cleared.
 
"SkipDefaultVerify" is checked by [[#VerifyOption|SetVerifyOption]] and "EnableAlpn" is only available with [[#SetOption_2|SetOption]].
 
[[#SetOption_2|SetOption]] with "DoNotCloseSocket" is only available when [[#SetSocketDescriptor]] was not used previously. "EnableAlpn" can optionally use the state setup by [[#SetSocketDescriptor]], but it will return 0 regardless.
 
See [[#SetNextAlpnProto]] for "EnableAlpn", and [[#DoHandshakeGetServerCert]] for "GetServerCertChain".
 
= AlpnProtoState =
This is "nn::ssl::sf::AlpnProtoState" or "nn::ssl::Connection::AlpnProtoState".
 
{| class="wikitable" border="1"
|-
|-
! Value
| 0x1C || 0x4 || Unknown.
! Description
|-
|-
| 0 || NoSupport
| 0x20 || 0x2 || Unknown.
|-
|-
| 1 || Negotiated
| 0x22 || 0x2 || Unknown.
|-
|-
| 2 || NoOverlap
| 0x24 || 0x2 || Unknown.
|-
|-
| 3 || Selected
| 0x26 || 0x2 || Unknown.
|-
|-
| 4 || EarlyValue
| 0x28 || 0x18 || Always zero.
|}
|}


= CipherInfo =
This is "nn::capsrv::ScreenShotAttributeForApplication". This is a 0x40-byte struct.
This is "nn::ssl::Connection::CipherInfo". This is a 0x48-byte struct.
 
Official sw only uses this in <code>nn::album</code> funcs which convert this to [[#AlbumFileAttribute]], with the output from [[#LoadAlbumScreenShotImageByAruid]]/[[#LoadAlbumScreenShotThumbnailImageByAruid]] (only the first u32 is used).


= AlbumFileAttribute =
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Offset
! Offset || Size || Description
! Size
! Description
|-
|-
| 0x0 || 0x40 || Cipher string
| 0x0 || 0x8 || The <code>nn::album</code> funcs referenced by [[#ScreenShotAttributeForApplication]] set this to: <code>ScreenShotAttributeForApplication.first_u32 == 2</code>.
|-
|-
| 0x40 || 0x8 || Protocol version string
| 0x8 || 0x8 || Set to zero by official sw.
|}
|}


= CertStore =
This is "nn::album::AlbumFileAttribute". This is a 0x10-byte struct. See also [[#ScreenShotAttributeForApplication]].
This is the CertStore title, which contains the following files in RomFS:
* "/ssl_TrustedCerts.bdf" ([1.0.0-2.3.0] "ssl_TrustedCerts.tcf") (file was renamed with [3.0.0], content is identical)
* [3.0.0+] "/ssl_Crl.bdf"
* [6.0.0+] "/ssl_CaFingerprints.bdf"
 
The content of this SystemData was updated with the following system-versions: [[3.0.0]], [[6.0.0]], [[8.0.0]]. See [[#CaCertificateId]] for the ssl_TrustedCerts changes.


[[#ISslContext]] automatically uses this CertStore, regardless of the used cmds.
= AlbumMovieReadStreamHandle =
This is "nn::capsrv::AlbumMovieReadStreamHandle" / "nn::album::MovieStreamHandle".


These have the following structure:
This is an u64 stream handle.
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x4 || Magic "sslT"
|-
| 0x4 || 0x4 || Total entries
|-
| 0x8 || 0x10*{total entries} || Array entries
|}


Array entry structure:
= Notes =
{| class="wikitable" border="1"
capsrv is responsible for validating the MACs for screenshots stored on the SD card, if the setting capsrv!enable_album_screenshot_filedata_verification is non-zero.
|-
! Offset
! Size
! Description
|-
| 0x0
| 0x4
| Id
|-
| 0x4
| 0x4
| [[#TrustedCertStatus]]
|-
| 0x8
| 0x4
| Data size
|-
| 0xC
| 0x4
| Data offset
|}


Data offset is relative to absolute offset 0x8.
Screenshots are validated as follows: The JPEG's MAC is extracted from the EXIF maker note, and stored. A timestamp string is generated by calling snprintf(&str, 20, "%04d:%02d:%02d %02d:%02d:%02d", ...); with stored timestamp values. If this doesn't match the timestamp string stored in EXIF, then an error 0xA34CE is returned. Otherwise, the entire JPEG is loaded into memory, and the stored EXIF maker note is cleared to zeroes. Then, an HMAC-SHA256 is computed over the entire JPEG using a hardcoded secret key. if (memcmp(calculated_hmac, stored_hmac, 0x10) == 0), the screenshot is valid, else 0xA3ACE is returned.


The Id is the same one used by service commands to access these entries. For ssl_TrustedCerts, Id is [[#CaCertificateId]].
In [[3.0.0]], MAC calculation was changed: now, instead of calculating an HMAC, a plain SHA256 hash is calculated. capsrv basically does screenshot_kek = spl::GenerateAesKek(<hardcoded screenshot_kek_source>); spl::LoadAesKey(screenshot_kek, <hardcoded screenshot_key_source>); MAC = spl::ComputeCmac(hash);


= Client cert+privk =
== Videos ==
SSL-sysmodule uses [[Settings_services|set:cal]] [[Settings_services#GetSslKey|GetSslKey]] and [[Settings_services#GetSslCert|GetSslCert]]. The rest of this section documents handling for the former, which can be decrypted with [[SPL_services|SPL]].
[[4.0.0]] includes video playback etc support in Album via mp4. These include a JPEG thumbnail, which is used for video "validation". The EXIF is also much larger: the MakerNote is 0x498-bytes, with encrypted data starting at offset +0x8. This encryption uses AES-CTR with hardcoded key/ctr. MAC calculation works the same way as the [[3.0.0]]+ JPEG MAC calculation, except with a different movie_kek_source/movie_key_source.


key* below refers to the 3 0x10-byte input blocks passed to this code.
Each 0x40000-byte chunk in the Movie data stream is validated with a SHA256 hash table, where hash_index=offset>>18. Whether an error is thrown on mismatch is controlled by [[System_Settings|system-setting]] "capsrv!enable_album_movie_filehash_verification".


When actual_size is:
Note: the Album process itself uses libstagefright for video playback.
* 0x100+0x10: If the u32 actual_size is less than (u32)-0x11, and the last 0x10-bytes of the actual-data are all-zero, the data is copied to the output as raw plaintext. If a non-zero byte is found, it will continue with [[SPL_services|SPL]] usage, skipping over the SPL block for the devunit flag. In this case, key=key0 and the flag passed to SPL later is set to 0.
* 0x100+0x30: Size must match this if it's not the above, otherwise error 0xC81A is returned. The flag passed to SPL later is set to 1 in this case. Runs the devunit-flag-block: uses [[SPL_services#SPL#GetDevunitFlag]]. key = key1 when out_flag!=0, key2 otherwise.


[[Category:Services]]
[[Category:Services]]

Revision as of 02:48, 7 July 2020

caps:a

This is "nn::capsrv::sf::IAlbumAccessorService".

Cmd Name
0 GetAlbumFileCount
1 GetAlbumFileList
2 LoadAlbumFile
3 DeleteAlbumFile
4 StorageCopyAlbumFile
5 IsAlbumMounted
6 GetAlbumUsage
7 GetAlbumFileSize
8 LoadAlbumFileThumbnail
9 [2.0.0+] LoadAlbumScreenShotImage
10 [2.0.0+] LoadAlbumScreenShotThumbnailImage
11 [2.0.0+] GetAlbumEntryFromApplicationAlbumEntry
12 [3.0.0+] LoadAlbumScreenShotImageEx
13 [3.0.0+] LoadAlbumScreenShotThumbnailImageEx
14 [3.0.0+] LoadAlbumScreenShotImageEx0
15 [4.0.0+] GetAlbumUsage3
16 [4.0.0+] GetAlbumMountResult
17 [4.0.0+] GetAlbumUsage16
18 [6.0.0+]
100 [5.0.0+] GetAlbumFileCountEx0
101 [5.0.0+] GetAlbumFileListEx0
202 [1.0.0-2.3.0] SaveEditedScreenShot
301 GetLastOverlayScreenShotThumbnail
302 [4.0.0+] GetLastOverlayMovieThumbnail
401 GetAutoSavingStorage
501 GetRequiredStorageSpaceSizeToCopyAll
1001 [3.0.0+] LoadAlbumScreenShotThumbnailImageEx0
1002 [3.0.0+] LoadAlbumScreenShotImageEx1
1003 [4.0.0+] LoadAlbumScreenShotThumbnailImageEx1
8001 ForceAlbumUnmounted
8002 ResetAlbumMountStatus
8011 RefreshAlbumCache
8012 GetAlbumCache
8013 [4.0.0+] GetAlbumCacheEx
8021 [2.0.0+] GetAlbumEntryFromApplicationAlbumEntryAruid
10011 SetInternalErrorConversionEnabled
50000 [6.0.0+] LoadMakerNoteInfoForDebug
60002 [4.0.0+] OpenAccessorSession

Cmd18: Takes a type-70 buffer and returns a bool. If the buffer is sufficient it writes two application ID's to the buffer (0x100000000001000 and 0x100000000001fff) and returns true. This is used by photoViewer to group all screenshots of applets.

Cmd1002: Takes a total of 0x38-bytes of input, two type-0x5 input buffers, and returns 0x20-bytes of output. [4.0.0+] No longer returns output, and now takes the following buffers instead: type-0x16, type-0x46, and type-0x6.

Cmd60002: Takes a total of 8-bytes of input, a PID, and returns an #IAlbumAccessorSession.

IAlbumAccessorSession

This is "nn::capsrv::sf::IAlbumAccessorSession".

This was added with [4.0.0+].

Cmd Name
2001 OpenAlbumMovieReadStream
2002 CloseAlbumMovieReadStream
2003 GetAlbumMovieReadStreamMovieDataSize
2004 ReadMovieDataFromAlbumMovieReadStream
2005 GetAlbumMovieReadStreamBrokenReason
2006 GetAlbumMovieReadStreamImageDataSize
2007 ReadImageDataFromAlbumMovieReadStream
2008 ReadFileAttributeFromAlbumMovieReadStream

caps:c

This is "nn::capsrv::sf::IAlbumControlService", previously "nn::capsrv::sf::ICaptureControllerService" with [1.0.0].

Cmd Name Notes
[1.0.0] 1 CaptureRawImage
[1.0.0] 2 CaptureRawImageWithTimeout
33 [7.0.0+]
[1.0.0] 1001 RequestTakingScreenShot
[1.0.0] 1002 RequestTakingScreenShotWithTimeout
[1.0.0] 1011 NotifyTakingScreenShotRefused
2001 NotifyAlbumStorageIsAvailable
2002 NotifyAlbumStorageIsUnavailable
2011 [2.0.0+] RegisterAppletResourceUserId
2012 [2.0.0+] UnregisterAppletResourceUserId
2013 [2.0.0+] GetApplicationIdFromAruid
2014 [2.0.0+] CheckApplicationIdRegistered
2101 [2.0.0+] GenerateCurrentAlbumFileId Takes an input u8 and u64, returns a 0x18-byte struct.
2102 [2.0.0+] GenerateApplicationAlbumEnrty
[2.0.0-3.0.2] 2201 SaveAlbumScreenShotFile
2202 [4.0.0+] SaveAlbumScreenShotFileEx
2301 [2.0.0+] SetOverlayScreenShotThumbnailData
2302 [4.0.0+] SetOverlayMovieThumbnailData
60001 [4.0.0+] OpenControlSession Takes a total of 8-bytes of input and a PID, returns an #IAlbumControlSession.

Cmd33

Takes an input u64 #ShimLibraryVersion, an u64 AppletResourceUserId, and a PID, no output.

This is used by caps:su SetShimLibraryVersion.

IAlbumControlSession

This is "nn::capsrv::sf::IAlbumControlSession".

This was added with [4.0.0+].

Cmd Name Notes
2001 OpenAlbumMovieReadStream
2002 CloseAlbumMovieReadStream
2003 GetAlbumMovieReadStreamMovieDataSize
2004 ReadMovieDataFromAlbumMovieReadStream
2005 GetAlbumMovieReadStreamBrokenReason
2006 GetAlbumMovieReadStreamImageDataSize
2007 ReadImageDataFromAlbumMovieReadStream
2008 ReadFileAttributeFromAlbumMovieReadStream
2401 OpenAlbumMovieWriteStream
2402 FinishAlbumMovieWriteStream
2403 CommitAlbumMovieWriteStream
2404 DiscardAlbumMovieWriteStream
2405 DiscardAlbumMovieWriteStreamNoDelete
2406 [7.0.0+] CommitAlbumMovieWriteStreamEx
2411 StartAlbumMovieWriteStreamDataSection
2412 EndAlbumMovieWriteStreamDataSection
2413 StartAlbumMovieWriteStreamMetaSection
2414 EndAlbumMovieWriteStreamMetaSection
2421 ReadDataFromAlbumMovieWriteStream
2422 WriteDataToAlbumMovieWriteStream
2424 WriteMetaToAlbumMovieWriteStream
2431 GetAlbumMovieWriteStreamBrokenReason
2433 GetAlbumMovieWriteStreamDataSize
2434 SetAlbumMovieWriteStreamDataSize

caps:u

This is "nn::capsrv::sf::IAlbumApplicationService".

This was added with [5.0.0+].

Official sw via the nn::album wrappers uses start_DateTime = YYYY-MM-DD 1970-01-01 with the rest set to all-zero, end_DateTime is the same except year = 3000. With #GetAlbumFileList0AafeAruidDeprecated, start_PosixTime = UTC 1999-12-31 00:00 (0x386BF200), and end_PosixTime = UTC 2100-01-01 00:00 (0xF4865700).

Cmd Name
32 [7.0.0+] #SetShimLibraryVersion
102 #GetAlbumFileList0AafeAruidDeprecated
103 #DeleteAlbumFileByAruid
104 #GetAlbumFileSizeByAruid
105 #DeleteAlbumFileByAruidForDebug
110 #LoadAlbumScreenShotImageByAruid
120 #LoadAlbumScreenShotThumbnailImageByAruid
130 #PrecheckToCreateContentsByAruid
140 [6.0.0+] #GetAlbumFileList1AafeAruidDeprecated
141 [6.0.0+] #GetAlbumFileList2AafeUidAruidDeprecated
142 [7.0.0+] #GetAlbumFileList3AaeAruid
143 [7.0.0+] #GetAlbumFileList4AaeUidAruid
60002 #OpenAccessorSessionForApplication

SetShimLibraryVersion

Takes an input u64 #ShimLibraryVersion, an u64 AppletResourceUserId, and a PID, no output.

GetAlbumFileList0AafeAruidDeprecated

Takes a type-0x6 output buffer containing an array of #ApplicationAlbumFileEntry, a PID, an u8 #ContentType, two s64s, and an u64 AppletResourceUserId. Returns an output u64 for total output entries (which is copied to a s32 by official sw).

The two s64s are the start/end PosixTime.

DeleteAlbumFileByAruid

Takes a PID, an input u8 #ContentType, an #ApplicationAlbumFileEntry, an AppletResourceUserId, and no output.

The #ContentType must match 3.

GetAlbumFileSizeByAruid

Takes a PID, an input #ApplicationAlbumFileEntry, an AppletResourceUserId, and returns an output u64.

This gets the filesize for the entire specified Album file.

DeleteAlbumFileByAruidForDebug

Takes a PID, an #ApplicationAlbumFileEntry, an AppletResourceUserId, and no output.

The cached value loaded from Settings_services#GetDebugModeFlag must be 1, otherwise an error is returned.

LoadAlbumScreenShotImageByAruid

Takes a PID, a type-0x16 output buffer containing a #LoadAlbumScreenShotImageOutputForApplication, a type-0x46 output buffer, a type-0x6 output buffer, an #ApplicationAlbumFileEntry, a #ScreenShotDecodeOption, and no output.

The type-0x46 buffer contains the RGBA8 image data. The type-0x6 buffer is a work buffer used for reading the entire AlbumFile, the buffer size must be at least the AlbumFile filesize (cleared before the cmd returns).

LoadAlbumScreenShotThumbnailImageByAruid

Takes a PID, a type-0x16 output buffer containing a #LoadAlbumScreenShotImageOutputForApplication, a type-0x46 output buffer, a type-0x6 output buffer, an #ApplicationAlbumFileEntry, a #ScreenShotDecodeOption, and no output.

The type-0x46 buffer contains the RGBA8 image data. The type-0x6 buffer is a work buffer used for reading the entire AlbumFile, the buffer size must be at least the AlbumFile filesize (cleared before the cmd returns).

PrecheckToCreateContentsByAruid

Takes a PID, an input u8 #ContentType, an u64, an AppletResourceUserId, and no output.

GetAlbumFileList1AafeAruidDeprecated

Takes a type-0x6 output buffer containing an array of #ApplicationAlbumFileEntry, a PID, an u8 #ContentType, two #AlbumFileDateTime, and an u64 AppletResourceUserId. Returns an output u64 for total output entries (which is copied to a s32 by official sw).

The first #AlbumFileDateTime is the start_DateTime, the second #AlbumFileDateTime is the end_DateTime. In the IPC rawdata, these use 2-byte alignment.

GetAlbumFileList2AafeUidAruidDeprecated

Takes a type-0x6 output buffer containing an array of #ApplicationAlbumFileEntry, a PID, an u8 #ContentType, two #AlbumFileDateTime, an u128 userID, and an u64 AppletResourceUserId. Returns an output u64 for total output entries (which is copied to a s32 by official sw).

The first #AlbumFileDateTime is the start_DateTime, the second #AlbumFileDateTime is the end_DateTime. In the IPC rawdata, these use 2-byte alignment.

GetAlbumFileList3AaeAruid

Takes a type-0x6 output buffer containing an array of #ApplicationAlbumEntry, a PID, an u8 #ContentType, two #AlbumFileDateTime, and an u64 AppletResourceUserId. Returns an output u64 for total output entries (which is copied to a s32 by official sw).

The first #AlbumFileDateTime is the start_DateTime, the second #AlbumFileDateTime is the end_DateTime. In the IPC rawdata, these use 2-byte alignment.

GetAlbumFileList4AaeUidAruid

Takes a type-0x6 output buffer containing an array of #ApplicationAlbumEntry, a PID, an u8 #ContentType, two #AlbumFileDateTime, an u128 userID, and an u64 AppletResourceUserId. Returns an output u64 for total output entries (which is copied to a s32 by official sw).

The first #AlbumFileDateTime is the start_DateTime, the second #AlbumFileDateTime is the end_DateTime. In the IPC rawdata, these use 2-byte alignment.

OpenAccessorSessionForApplication

Takes a PID, an input #ApplicationAlbumFileEntry, an u64 AppletResourceUserId, and returns an output #IAlbumAccessorApplicationSession.

IAlbumAccessorApplicationSession

This is "nn::capsrv::sf::IAlbumAccessorApplicationSession".

This was added with [5.0.0+].

This is opened prior to using #OpenAlbumMovieReadStream, when it previously wasn't opened. Official sw only closes this session when closing caps:u, not when using #CloseAlbumMovieReadStream.

Cmd Name
2001 #OpenAlbumMovieReadStream
2002 #CloseAlbumMovieReadStream
2003 #GetAlbumMovieReadStreamMovieDataSize
2004 #ReadMovieDataFromAlbumMovieReadStream
2005 #GetAlbumMovieReadStreamBrokenReason

OpenAlbumMovieReadStream

Takes a PID, an input #ApplicationAlbumFileEntry, an u64 AppletResourceUserId, and returns an output u64 #AlbumMovieReadStreamHandle.

Up to 4 streams can be open at the same time. Multiple streams can be open at the same time for the same #ApplicationAlbumFileEntry.

CloseAlbumMovieReadStream

Takes an input u64 #AlbumMovieReadStreamHandle, no output.

GetAlbumMovieReadStreamMovieDataSize

Takes an input u64 #AlbumMovieReadStreamHandle, returns an output u64.

This gets the size of the actual MP4, without the JPEG at the end.

ReadMovieDataFromAlbumMovieReadStream

Takes a type-0x6 output buffer, an input u64 #AlbumMovieReadStreamHandle, an input s64 offset, and returns an output u64 actual_size.

offset(+size) must not be negative. offset and size must be aligned to 0x40000-bytes. When offset(+size) goes beyond the size from #GetAlbumMovieReadStreamMovieDataSize, the regions of the buffer which goes beyond that are cleared to 0, and actual_size is still set to the input size.

GetAlbumMovieReadStreamBrokenReason

Takes an input u64 #AlbumMovieReadStreamHandle, no output.

Unused by official sw.

ShimLibraryVersion

This is a version field. Official sw uses func nn::capsrv::GetShimLibraryVersion() to load this from a global var, which is then used with various commands (the input for those cmds must match value 1).

[7.0.0-9.0.0] This is value 1.

Controls which struct version to use for #ApplicationAlbumEntry / #AlbumFileEntry. However, the struct size for the newer version is used regardless on [7.0.0+] for the actual cmds.

Enums

AlbumImageOrientation

Value Description
0 Unknown.
1 Unknown.
2 Unknown.
3 Unknown.

This is "nn::album::ImageOrientation".

AlbumReportOption

Value Description
0 Don't display the screenshot-taken Overlay-applet notification.
1 Display the screenshot-taken Overlay notification.

This is "nn::album::AlbumReportOption".

ContentType

Value Description
0 Screenshot. Album screenshots.
1 Movie. Album videos.
3 ExtraMovie. Videos recorded by the current Application title via GRC MovieMaker.

AlbumStorage

Value Description
0 Nand. ImageDirectory on the USER partition.
1 Sd. ImageDirectory on the Sd card

AlbumFileDateTime

Offset Size Description
0x0 0x2 Year
0x2 0x1 Month
0x3 0x1 Day
0x4 0x1 Hour
0x5 0x1 Minute
0x6 0x1 Second
0x7 0x1 Unique ID for when there's multiple Album files with the same timestamp.

This is "nn::capsrv::AlbumFileDateTime". This is a 0x8-byte struct.

This corresponds to each field in the Album entry filename, prior to the "-": YYYYMMDDHHMMSSII.

AlbumEntry

Offset Size Description
0x0 0x8 Size of the entry.
0x8 0x8 ApplicationId
0x10 0x8 #AlbumFileDateTime
0x18 0x1 #AlbumStorage
0x19 0x1 #ContentType
0x1A 0x6 Padding.

This is "nn::capsrv::AlbumEntry". This is a 0x20-byte struct.

AlbumFileEntry

This is "nn::album::AlbumFileEntry". This is identical to #ApplicationAlbumEntry. On older versions where official sw used to use cmds which use #ApplicationAlbumFileEntry, this struct matches #ApplicationAlbumFileEntry.

ApplicationAlbumEntry

Offset Size Description
0x0 0x8 Size of the entry.
0x8 0x8 AES256 with hardcoded key over AlbumEntry.
0x10 0x8 #AlbumFileDateTime
0x18 0x1 #AlbumStorage
0x19 0x1 #ContentType
0x1a 0x5 Padding.
0x1f 0x1 Unknown. Set to 1 by official software.

This is "nn::capsrv::ApplicationAlbumEntry". This is a 0x20-byte struct. On older versions where #ShimLibraryVersion is 0, this was a plain AES256 with a random key generated at application launch.

With the output from caps:su sdk-nso only uses this for the Share-applet (when the output is used at all), with everything else it's used as an #AlbumFileEntry. In those cases with the nn::album wrapper funcs, it's "converted" by just copying the struct (arrays are "converted" by just returning a ptr to the input array).

ApplicationAlbumFileEntry

Offset Size Description
0x0 0x20 #ApplicationAlbumEntry
0x20 0x8 #AlbumFileDateTime
0x28 0x8 Unknown.

This is "nn::capsrv::ApplicationAlbumFileEntry". This is a 0x30-byte struct.

On newer versions where official sw uses #ApplicationAlbumEntry, #ApplicationAlbumEntry is converted to ApplicationAlbumFileEntry when using cmds which need it with:

  • First 0x20-bytes are the same.
  • u64 ApplicationAlbumFileEntry+0x20 = #ApplicationAlbumEntry+0x10.
  • Last 8-bytes = 0.

ScreenShotAttribute

Offset Size Description
0x0 0x4 Always set to 0 by official sw.
0x4 0x4 #AlbumImageOrientation
0x8 0x4 Always set to 0 by official sw.
0xC 0x4 Always set to 1 by official sw.
0x10 0x30 Always set to 0 by official sw.

This is "nn::capsrv::detail::ScreenShotAttributeEx0" / "nn::capsrv::ScreenShotAttribute". This is a 0x40-byte struct.

ApplicationData

Offset Size Description
0x0 0x400 UserData
0x400 0x4 UserData size.

This is "nn::capsrv::ApplicationData". This is a 0x404-byte struct.

UserIdList

Offset Size Description
0x0 0x80 u128 userIDs
0x80 0x1 Total userIDs.
0x81 0x7 Padding.

This is "nn::capsrv::UserIdList". This is a 0x88-byte struct.

LoadAlbumScreenShotImageOutputForApplication

Offset Size Description
0x0 0x8 s64 Width. Official sw copies this to a s32 output field.
0x8 0x8 s64 Height. Official sw copies this to a s32 output field.
0x10 0x40 #ScreenShotAttributeForApplication
0x50 0x404 #ApplicationData
0x454 0xAC Unused

This is "nn::capsrv::sf::LoadAlbumScreenShotImageOutputForApplication". This is a 0x500-byte struct.

ScreenShotDecodeOption

This is "nn::capsrv::ScreenShotDecodeOption". This is a 0x20-byte struct.

Official sw sets this to all-zero with the input for #LoadAlbumScreenShotImageByAruid/#LoadAlbumScreenShotThumbnailImageByAruid.

ScreenShotAttributeForApplication

Offset Size Description
0x0 0x4 Unknown.
0x4 0x1 Unknown.
0x5 0x1 Unknown.
0x6 0x1 Unknown.
0x7 0x1 Padding.
0x8 0x4 Unknown.
0xC 0x4 Unknown.
0x10 0x4 Unknown.
0x14 0x4 Unknown.
0x18 0x4 Unknown.
0x1C 0x4 Unknown.
0x20 0x2 Unknown.
0x22 0x2 Unknown.
0x24 0x2 Unknown.
0x26 0x2 Unknown.
0x28 0x18 Always zero.

This is "nn::capsrv::ScreenShotAttributeForApplication". This is a 0x40-byte struct.

Official sw only uses this in nn::album funcs which convert this to #AlbumFileAttribute, with the output from #LoadAlbumScreenShotImageByAruid/#LoadAlbumScreenShotThumbnailImageByAruid (only the first u32 is used).

AlbumFileAttribute

Offset Size Description
0x0 0x8 The nn::album funcs referenced by #ScreenShotAttributeForApplication set this to: ScreenShotAttributeForApplication.first_u32 == 2.
0x8 0x8 Set to zero by official sw.

This is "nn::album::AlbumFileAttribute". This is a 0x10-byte struct. See also #ScreenShotAttributeForApplication.

AlbumMovieReadStreamHandle

This is "nn::capsrv::AlbumMovieReadStreamHandle" / "nn::album::MovieStreamHandle".

This is an u64 stream handle.

Notes

capsrv is responsible for validating the MACs for screenshots stored on the SD card, if the setting capsrv!enable_album_screenshot_filedata_verification is non-zero.

Screenshots are validated as follows: The JPEG's MAC is extracted from the EXIF maker note, and stored. A timestamp string is generated by calling snprintf(&str, 20, "%04d:%02d:%02d %02d:%02d:%02d", ...); with stored timestamp values. If this doesn't match the timestamp string stored in EXIF, then an error 0xA34CE is returned. Otherwise, the entire JPEG is loaded into memory, and the stored EXIF maker note is cleared to zeroes. Then, an HMAC-SHA256 is computed over the entire JPEG using a hardcoded secret key. if (memcmp(calculated_hmac, stored_hmac, 0x10) == 0), the screenshot is valid, else 0xA3ACE is returned.

In 3.0.0, MAC calculation was changed: now, instead of calculating an HMAC, a plain SHA256 hash is calculated. capsrv basically does screenshot_kek = spl::GenerateAesKek(<hardcoded screenshot_kek_source>); spl::LoadAesKey(screenshot_kek, <hardcoded screenshot_key_source>); MAC = spl::ComputeCmac(hash);

Videos

4.0.0 includes video playback etc support in Album via mp4. These include a JPEG thumbnail, which is used for video "validation". The EXIF is also much larger: the MakerNote is 0x498-bytes, with encrypted data starting at offset +0x8. This encryption uses AES-CTR with hardcoded key/ctr. MAC calculation works the same way as the 3.0.0+ JPEG MAC calculation, except with a different movie_kek_source/movie_key_source.

Each 0x40000-byte chunk in the Movie data stream is validated with a SHA256 hash table, where hash_index=offset>>18. Whether an error is thrown on mismatch is controlled by system-setting "capsrv!enable_album_movie_filehash_verification".

Note: the Album process itself uses libstagefright for video playback.