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.
internal_sockfd = output from 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 DoNotCloseSocket is set it will instead return -1 for the sockfd. Then 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.
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.
This gets the input_sockfd which was previously saved in state by #SetSocketDescriptor.
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.
#SetSocketDescriptor must have been used prior to this successfully.
The hostname must be set (non-empty string) when #VerifyOption HostName is set, otherwise an error is thrown.
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.
The u32 is the timeout in milliseconds.
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.
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.
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 | [3.0.0+] 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 ([8.0.0+] #TrustedCertStatus is EnabledNotTrusted) |
1018 | GeoTrustGlobalCA ([8.0.0+] #TrustedCertStatus is EnabledNotTrusted) |
1019 | GeoTrustPrimaryCertificationAuthorityG3 ([8.0.0+] #TrustedCertStatus is EnabledNotTrusted) |
1020 | GeoTrustPrimaryCertificationAuthority ([8.0.0+] #TrustedCertStatus is EnabledNotTrusted) |
1021 | GlobalSignRootCA |
1022 | GlobalSignRootCAR2 |
1023 | GlobalSignRootCAR3 |
1024 | GoDaddyClass2CertificationAuthority |
1025 | GoDaddyRootCertificateAuthorityG2 |
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 |
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".
The default value for CrlImportDateCheckEnable at the time of #ISslContext object creation is value 1.
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_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.
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 | #TrustedCertStatus |
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.