SSL services
ssl
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.
Cmd | Name |
---|---|
0 | #CreateContext |
1 | #GetContextCount |
2 | #GetCertificates |
3 | #GetCertificateBufSize |
4 | [3.0.0+] #DebugIoctl |
5 | [3.0.0+] #SetInterfaceVersion |
6 | [5.0.0+] #FlushSessionCache |
7 | [6.0.0+] #SetDebugOption |
8 | [6.0.0+] #GetDebugOption |
CreateContext
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
Takes a type-0x5 input buffer containing an array of #CaCertificateId, returns an output u32 for the size to use with #GetCertificates.
DebugIoctl
Stubbed on retail, just returns an error.
SetInterfaceVersion
Takes an input u32 version, no output.
Used by user-processes during service init.
Value | SystemVersion |
---|---|
0x1 | [3.0.0+] |
0x2 | [5.0.0+] |
0x3 | [6.0.0+] |
FlushSessionCache
Takes a type-0x5 input buffer, an input u32 #FlushSessionCacheOptionType, returns an output u32.
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 nn::ssl::SetDebugOption
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".
Cmd | Name |
---|---|
0 | #SetOption |
1 | #GetOption |
2 | #CreateConnection |
3 | #GetConnectionCount |
4 | #ImportServerPki |
5 | #ImportClientPki |
6 | #RemoveServerPki |
7 | #RemoveClientPki |
8 | #RegisterInternalPki |
9 | #AddPolicyOid |
10 | [3.0.0+] #ImportCrl |
11 | [3.0.0+] #RemoveCrl |
SetOption
Takes an input #ContextOption and an input s32, 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.
ImportServerPki
Takes a type-0x5 input buffer and a #CertificateFormat, returns an output u64.
ImportClientPki
Takes two type-0x5 input buffers, returns an output u64.
RemoveServerPki
Takes an input u64, no output.
RemoveClientPki
Takes an input u64, no output.
RegisterInternalPki
Takes an input #InternalPki, returns an output u64.
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.
RemoveCrl
Takes an input u64, no output.
ISslConnection
This is "nn::ssl::sf::ISslConnection".
Cmd | Name |
---|---|
0 | #SetSocketDescriptor |
1 | #SetHostName |
2 | #SetVerifyOption |
3 | #SetIoMode |
4 | #GetSocketDescriptor |
5 | #GetHostName |
6 | #GetVerifyOption |
7 | #GetIoMode |
8 | #DoHandshake |
9 | #DoHandshakeGetServerCert |
10 | #Read |
11 | #Write |
12 | #Pending |
13 | #Peek |
14 | #Poll |
15 | #GetVerifyCertError |
16 | #GetNeededServerCertBufferSize |
17 | #SetSessionCacheMode |
18 | #GetSessionCacheMode |
19 | #FlushSessionCache |
20 | #SetRenegotiationMode |
21 | #GetRenegotiationMode |
22 | SetOption |
23 | GetOption |
24 | #GetVerifyCertErrors |
25 | [4.0.0+] #GetCipherInfo |
26 | [9.0.0+] #SetNextAlpnProto |
27 | [9.0.0+] #GetNextAlpnProto |
SetSocketDescriptor
Takes an input s32 sockfd, returns an output s32 sockfd.
An error is thrown if this was used previously.
The input sockfd is used with DuplicateSocket, with the output sockfd from that being written into state. If the field which would be used for the input u64 is zero however, it instead uses the input sockfd directly and returns -1 for the sockfd. An error is thrown if DuplicateSocket fails. When DuplicateSocket is successful, the input sockfd is returned as the output sockfd, however if DoNotCloseSocket is set it will instead return -1 for the sockfd.
Immediately prior to closing the #ISslConnection object, sdknso will close the sockfd which was returned by this cmd if it is not negative.
SetHostName
Takes a type-0x5 input buffer, no output.
The input buffer contains a string, the buffer size must be <=0xFF.
The buffer is copied to a tmpbuf, then nsd ResolveEx is used with this tmpbuf to set the HostName in state.
SetVerifyOption
Takes an input u32 #VerifyOption, no output.
SetIoMode
Takes an input #IoMode, no output.
#SetSocketDescriptor must have been used prior to this successfully.
GetSocketDescriptor
No input, returns an output s32.
#SetSocketDescriptor must have been used prior to this successfully.
GetHostName
Takes a type-0x6 output buffer, returns an output u32.
The output u32 is the string length (buffer must be large enough for the entire string).
GetVerifyOption
No input, returns an output u32 #VerifyOption.
GetIoMode
No input, returns an output #IoMode.
DoHandshake
No input/output.
This will also set a callback eventually for saving an error-report when needed, which just contains the ErrorCode loaded from a Result in state. This sysmodule doesn't save any other reports elsewhere.
DoHandshakeGetServerCert
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.
Read
Takes a type-0x6 output buffer, returns an output u32.
#SetSocketDescriptor must have been used prior to this successfully.
Write
Takes a type-0x5 input buffer, returns an output u32.
#SetSocketDescriptor must have been used prior to this successfully.
Pending
No input, returns an output s32.
#SetSocketDescriptor must have been used prior to this successfully.
Peek
Takes a type-0x6 output buffer, returns an output u32.
#SetSocketDescriptor must have been used prior to this successfully.
Poll
Takes an input #PollEvent, an u32, returns an output #PollEvent.
#SetSocketDescriptor must have been used prior to this successfully.
GetVerifyCertError
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.
GetNeededServerCertBufferSize
No input, returns an output u32.
This just copies an u32 from state to output and returns 0.
SetSessionCacheMode
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.
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.
GetNextAlpnProto
Takes a type-0x6 output buffer, returns an output #AlpnProtoState and an output u32.
#SetSocketDescriptor must have been used prior to this successfully.
SslVersion
This is "nn::ssl::sf::SslVersion" or "nn::ssl::Context::SslVersion".
Value | Description |
---|---|
0x1 | Auto |
0x8 | TlsV10 |
0x10 | TlsV11 |
0x20 | TlsV12 |
DebugOptionType
This is "nn::ssl::sf::DebugOptionType" or "nn::ssl::DebugOption".
Value | Description |
---|---|
0 | AllowDisableVerifyOption |
FlushSessionCacheOptionType
This is "nn::ssl::sf::FlushSessionCacheOptionType" or "nn::ssl::FlushSessionCacheOptionType".
Value | Description |
---|---|
0 | SingleHost |
1 | AllHosts |
BuiltInCertificateInfo
This is "nn::ssl::BuiltInManager::BuiltInCertificateInfo".
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | #CaCertificateId |
0x4 | 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.
TrustedCertStatus
This is "nn::ssl::TrustedCertStatus".
Value | Description |
---|---|
-1 | Invalid |
0 | Removed |
1 | EnabledTrusted |
2 | EnabledNotTrusted |
3 | Revoked |
CaCertificateId
This is "nn::ssl::CaCertificateId".
Value | Description |
---|---|
-1 | All |
1 | NintendoCAG3 |
2 | NintendoClass2CAG3 |
1000 | AmazonRootCA1 |
1001 | StarfieldServicesRootCertificateAuthorityG2 |
1002 | AddTrustExternalCARoot |
1003 | COMODOCertificationAuthority |
1004 | UTNDATACorpSGC |
1005 | UTNUSERFirstHardware |
1006 | BaltimoreCyberTrustRoot |
1007 | CybertrustGlobalRoot |
1008 | VerizonGlobalRootCA |
1009 | DigiCertAssuredIDRootCA |
1010 | DigiCertAssuredIDRootG2 |
1011 | DigiCertGlobalRootCA |
1012 | DigiCertGlobalRootG2 |
1013 | DigiCertHighAssuranceEVRootCA |
1014 | EntrustnetCertificationAuthority2048 |
1015 | EntrustRootCertificationAuthority |
1016 | EntrustRootCertificationAuthorityG2 |
1017 | GeoTrustGlobalCA2 |
1018 | GeoTrustGlobalCA |
1019 | GeoTrustPrimaryCertificationAuthorityG3 |
1020 | GeoTrustPrimaryCertificationAuthority |
1021 | GlobalSignRootCA |
1022 | GlobalSignRootCAR2 |
1023 | GlobalSignRootCAR3 |
1024 | GoDaddyClass2CertificationAuthority |
1025 | GoDaddyRootCertificateAuthorityG2 |
1026 | StarfieldClass2CertificationAuthority |
1027 | StarfieldRootCertificateAuthorityG2 |
1028 | thawtePrimaryRootCAG3 |
1029 | thawtePrimaryRootCA |
1030 | VeriSignClass3PublicPrimaryCertificationAuthorityG3 |
1031 | VeriSignClass3PublicPrimaryCertificationAuthorityG5 |
1032 | VeriSignUniversalRootCertificationAuthority |
1033 | DSTRootCAX3 |
InternalPki
This is "nn::ssl::sf::InternalPki" or "nn::ssl::Context::InternalPki".
Value | Description |
---|---|
0 | None |
1 | DeviceClientCertDefault |
An error is thrown by #RegisterInternalPki when the input value does not match "DeviceClientCertDefault".
ContextOption
This is "nn::ssl::sf::ContextOption" or "nn::ssl::Context::ContextOption".
Value | Description |
---|---|
0 | None |
1 | CrlImportDateCheckEnable |
CertificateFormat
This is "nn::ssl::sf::CertificateFormat" or "nn::ssl::CertificateFormat".
Value | Description |
---|---|
1 | Pem |
2 | Der |
VerifyOption
This is "nn::ssl::sf::VerifyOption". This is a bitmask. At the time of #ISslConnection object creation, the default value is 0x3.
Bit | Description |
---|---|
0 | PeerCa |
1 | HostName |
2 | DateCheck |
3 | EvCertPartial |
4 | [6.0.0+] EvPolicyOid |
5 | [6.0.0+] EvCertFingerprint |
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 InterfaceVersion is >=0x2, the low 2-bits of VerifyOption must be set, unless {state flag for SkipDefaultVerify} is set or [9.0.0+] {bool 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.
IoMode
This is "nn::ssl::sf::IoMode" or "nn::ssl::Connection::IoMode". At the time of #ISslConnection object creation, the default value is 1.
Value | Description |
---|---|
1 | Blocking |
2 | NonBlocking |
PollEvent
This is "nn::ssl::sf::PollEvent" or "nn::ssl::Connection::PollEvent". This is a bitmask.
Bit | Description |
---|---|
0 | Read |
1 | Write |
2 | Except |
SessionCacheMode
This is "nn::ssl::sf::SessionCacheMode" or "nn::ssl::Connection::SessionCacheMode".
Value | Description |
---|---|
0 | None |
1 | SessionId |
2 | SessionTicket |
RenegotiationMode
This is "nn::ssl::sf::RenegotiationMode" or "nn::ssl::Connection::RenegotiationMode".
Value | Description |
---|---|
0 | None |
1 | Secure |
OptionType
This is "nn::ssl::sf::OptionType" or "nn::ssl::Connection::OptionType".
Value | Description |
---|---|
0 | DoNotCloseSocket |
1 | [3.0.0+] GetServerCertChain |
2 | [5.0.0+] SkipDefaultVerify |
3 | [9.0.0+] EnableAlpn |
This corresponds to bool flags. At the time of #ISslConnection object creation, all of these bool flags are cleared.
"SkipDefaultVerify" is checked by SetVerifyOption and "EnableAlpn" is only available with SetOption.
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.
AlpnProtoState
This is "nn::ssl::sf::AlpnProtoState" or "nn::ssl::Connection::AlpnProtoState".
Value | Description |
---|---|
0 | NoSupport |
1 | Negotiated |
2 | NoOverlap |
3 | Selected |
4 | EarlyValue |
CipherInfo
This is "nn::ssl::Connection::CipherInfo". This is a 0x48-byte struct.
Offset | Size | Description |
---|---|---|
0x0 | 0x40 | Cipher string |
0x40 | 0x8 | Protocol version string |
CertStore
This is the CertStore title, which contains the following files in RomFS:
- "/ssl_CaFingerprints.bdf"
- "/ssl_Crl.bdf"
- "/ssl_TrustedCerts.bdf"
On old system-versions, this only contains "/ssl_TrustedCerts.tcf", which seems to have the same format described below.
These have the following structure:
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Magic "sslT" |
0x4 | 0x4 | Total entries |
0x8 | 0x10*{total entries} | Array entries |
Array entry structure:
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Id |
0x4 | 0x4 | ? |
0x8 | 0x4 | Data size |
0xC | 0x4 | Data offset |
Data offset is relative to absolute offset 0x8.
The ID is the same one used by service commands to access these entries. For ssl_TrustedCerts, ID is #CaCertificateId.
Client cert+privk
SSL-sysmodule uses set:cal GetSslKey and GetSslCert. The rest of this section documents handling for the former, which can be decrypted with SPL.
key* below refers to the 3 0x10-byte input blocks passed to this code.
When actual_size is:
- 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 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.