SSL services: Difference between revisions

Created page with "=ssl= =Client cert+privk= SSL-sysmodule uses set:cal GetTLSClientPrivk and GetTLSClientCert. The rest of this section documents handling for the former,..."
 
 
(152 intermediate revisions by 3 users not shown)
Line 1: Line 1:
=ssl=
= ssl =
This is "nn::ssl::sf::ISslService".


=Client cert+privk=
The 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.
SSL-sysmodule uses [[Settings_services|set:cal]] GetTLSClientPrivk and GetTLSClientCert. The rest of this section documents handling for the former, which can be decrypted with [[SPL_services|SPL]].
 
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.
 
This has IPC max_sessions = 0x40.
 
{| class="wikitable" border="1"
|-
! 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]]
|-
| 9 || [14.0.0+] [[#ClearTls12FallbackFlag]]
|}
 
== 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.
 
{| class="wikitable" border="1"
|-
! Value || SystemVersion
|-
| 0x1 || [3.0.0+]
|-
| 0x2 || [5.0.0+]
|-
| 0x3 || [6.0.0+]
|-
| 0x4 || [20.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 <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.
 
== ClearTls12FallbackFlag ==
No input/output.
 
== ISslContext ==
This is "nn::ssl::sf::ISslContext".
 
{| class="wikitable" border="1"
|-
! 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]]
|-
| 12 || [16.0.0+] [[#ImportClientCertKeyPki]]
|-
| 13 || [16.0.0+] [[#GeneratePrivateKeyAndCert]]
|}
 
=== 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 Id.
 
The input buffer can contain multiple certs. A maximum of 71 ServerPki objects (associated with the output Id) can be imported.
 
The certs can be CAs or server certs (no pubkeys).
 
The [[#CertificateFormat]] only validated, afterwards it's ignored.
 
=== 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.
 
=== ImportClientCertKeyPki ===
Takes two type-0x5 input buffers and a [[#CertificateFormat]], returns an output u64 Id.
 
This imports the specified client cert (first inbuf) and key (second inbuf). The [[#CertificateFormat]] controls the format for the cert and key.
 
=== GeneratePrivateKeyAndCert ===
Takes two type-0x6 output buffers, a type-0x5 input buffer containing a [[#KeyAndCertParams]], and an u32, returns two output u32s.
 
Official sw passes hard-coded value 1 for the u32. Sysmodule will throw an error if the u32 is not value 1.
 
The input buffer size must match the size of [[#KeyAndCertParams]] (0x58-bytes).
 
This generates a self-signed DER cert/key with algo sha256WithRSAEncryption, with the cert expiring in exactly 30 days from the begin-timestamp.
 
The first outbuf contains the cert, the second outbuf contains the key. The output u32s are the actual output size of the cert and key.
 
Sample cert:
 
  Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number: {...}
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = {input}
        Validity
            Not Before: {...}
            Not After : {...}
        Subject: CN = {input}
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: {input bit-size}
                Modulus:
                    {...}
                Exponent: {input}
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        {...}
 
=== ISslConnection ===
This is "nn::ssl::sf::ISslConnection".
 
{| class="wikitable" border="1"
|-
! 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_2|SetOption]]
|-
| 23 || [[#GetOption_2|GetOption]]
|-
| 24 || [[#GetVerifyCertErrors]]
|-
| 25 || [4.0.0+] [[#GetCipherInfo]]
|-
| 26 || [9.0.0+] [[#SetNextAlpnProto]]
|-
| 27 || [9.0.0+] [[#GetNextAlpnProto]]
|-
| 28 || [16.0.0+] [[#SetDtlsSocketDescriptor]]
|-
| 29 || [16.0.0+] [[#GetDtlsHandshakeTimeout]]
|-
| 30 || [16.0.0+] [[#SetPrivateOption]]
|-
| 31 || [16.0.0+] [[#SetSrtpCiphers]]
|-
| 32 || [16.0.0+] [[#GetSrtpCipher]]
|-
| 33 || [16.0.0+] [[#ExportKeyingMaterial]]
|-
| 34 || [16.0.0+] [[#SetIoTimeout]]
|-
| 35 || [16.0.0+] [[#GetIoTimeout]]
|-
| 36 || [20.0.0+] GetSessionTicket
|-
| 37 || [20.0.0+] SetSessionTicket
|}
 
==== SetSocketDescriptor ====
Takes an input s32 sockfd, returns an output s32 sockfd.
 
An error is thrown if this was used previously.
 
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.
 
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 [[Sockets_services|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 [[#SetHostName|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_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.
 
==== 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.
 
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.
 
When [[#OptionType|GetServerCertChain]] is set, the output buffer contains the full chain. This buffer can then be parsed by a seperate sdknso func:
* 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.
 
When [[#IoMode]] is NonBlocking the buffer will be only filled in once - when this cmd returns successfully the buffer will generally be empty.
 
==== Read ====
Takes a type-0x6 output buffer, returns an output u32.
 
[[#SetSocketDescriptor]] must have been used prior to this successfully.
 
The output u32 is the actual transferred size.
 
==== Write ====
Takes a type-0x5 input buffer, returns an output u32.
 
[[#SetSocketDescriptor]] must have been used prior to this successfully.
 
The output u32 is the actual transferred size.
 
==== 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 size.
 
[[#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.
 
[[#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*.
 
==== SetDtlsSocketDescriptor ====
Takes an input s32 sockfd and a type-0x5 input buffer, returns an output s32 sockfd.
 
The input buffer contains a "nn::socket::SockAddr".
 
The input buffer must be at least 0x10-bytes and the byte at buf+0 must match the buffer size, otherwise an error is thrown. Then the same func is called as [[#SetSocketDescriptor]] internally, except this passes the input buffer for the SockAddr, while SetSocketDescriptor passes NULL for SockAddr.
 
==== GetDtlsHandshakeTimeout ====
Takes a type-0x6 output buffer containing a "nn::TimeSpan".
 
The buffer size must be 0x8.
 
==== SetPrivateOption ====
Takes an input bool and an [[#OptionType]], no output.
 
[17.0.0+] Takes an input u32 value and an [[#OptionType]], no output.
 
==== SetSrtpCiphers ====
Takes a type-0x5 input buffer, no output.
 
The buffer must be aligned to 2-bytes. The buffer contains an array of u16s, a maximum of 4 entries is allowed. Each entry must be value 1-2, otherwise the entry is ignored.
 
==== GetSrtpCipher ====
No input, returns an output u16.
 
==== ExportKeyingMaterial ====
Takes a type-0x6 output buffer and two type-0x5 input buffers.
 
The first inbuf contains the label string. The buffer size must match the output from strnlen(inbuf0, bufsize0), therefore the buffer size must not include the NUL-terminator.
 
The second inbuf is the optional context data, if specified the buffer size must be <0xFFFF.
 
This is for standard TLS keying material export.
 
==== SetIoTimeout ====
Takes an input u32, no output.
 
This sets a field in the ISslConnection object, then returns 0.
 
==== GetIoTimeout ====
No input, returns an output u32.
 
This gets the field set by [[#SetIoTimeout]], then returns 0.
 
= ssl:s =
This is "nn::ssl::sf::ISslServiceForSystem".
 
This was added with [15.0.0+].
 
This has IPC max_sessions = 0x40.
 
{| class="wikitable" border="1"
|-
! Cmd || Name
|-
| 0 || [[#CreateContext]]
|-
| 1 || [[#GetContextCount]]
|-
| 2 || [[#GetCertificates]]
|-
| 3 || [[#GetCertificateBufSize]]
|-
| 4 || [[#DebugIoctl]]
|-
| 5 || [[#SetInterfaceVersion]]
|-
| 6 || [[#FlushSessionCache]]
|-
| 7 || [[#SetDebugOption]]
|-
| 8 || [[#GetDebugOption]]
|-
| 9 || [[#ClearTls12FallbackFlag]]
|-
| 100 || [[#CreateContextForSystem]]
|-
| 101 || [[#SetThreadCoreMask]]
|-
| 102 || [[#GetThreadCoreMask]]
|-
| 103 || [18.0.0+] [[#VerifySignature]]
|}
 
== CreateContextForSystem ==
Takes a PID, an input u32 [[#SslVersion]] and an input u64 pid_placeholder. Returns an output [[#ISslContextForSystem]].
 
== SetThreadCoreMask ==
Takes an input u64 mask, no output.
 
An error is thrown if the mask is 0, or if any bits are set which are not present in CoreMask from [[SVC|svcGetInfo]].
 
This updates a global field and uses [[SVC|svcSetThreadCoreMask]].
 
== GetThreadCoreMask ==
No input, returns an output u64.
 
This gets the global field which is also used by [[#SetThreadCoreMask]].
 
== VerifySignature ==
Takes three type-0x5 input buffers. No output.
 
[19.0.0+] Now takes an additional 4-bytes of input.
 
== ISslContextForSystem ==
This is "nn::ssl::sf::ISslContextForSystem".
 
This was added with [15.0.0+].
 
{| class="wikitable" border="1"
|-
! Cmd || Name
|-
| 0 || [[#SetOption]]
|-
| 1 || [[#GetOption]]
|-
| 2 || [[#CreateConnection]]
|-
| 3 || [[#GetConnectionCount]]
|-
| 4 || [[#ImportServerPki]]
|-
| 5 || [[#ImportClientPki]]
|-
| 6 || [[#RemoveServerPki]]
|-
| 7 || [[#RemoveClientPki]]
|-
| 8 || [[#RegisterInternalPki]]
|-
| 9 || [[#AddPolicyOid]]
|-
| 10 || [[#ImportCrl]]
|-
| 11 || [[#RemoveCrl]]
|-
| 12 || [16.0.0+] [[#ImportClientCertKeyPki]]
|-
| 13 || [16.0.0+] [[#GeneratePrivateKeyAndCert]]
|-
| 100 || [[#CreateConnectionEx]]
|}
 
=== CreateConnectionEx ===
No input. Returns an [[#ISslConnection]].
 
This is similar to [[#CreateConnection]], but allows a maximum of 10 connections instead of 8.
 
= 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=TlsV10 max=TlsV12.
 
[11.0.0+] ApiVersion is 1.
 
[12.0.0+] ApiVersion is now 2. Auto now uses min=TlsV10 max=((ApiVersion < 2) ? TlsV12 : TlsV13).
 
[12.0.3+] TLS 1.3 is no longer used. The TlsV13 bit is now handled the same as TlsV12 (uses TLS 1.2), and Auto only uses TLS 1.2 for the maximum.
 
[14.0.0+] ApiVersion is now 3 and TLS 1.3 is supported again. Auto now uses min=TlsV10 max=((ApiVersion < 3) ? TlsV12 : TlsV13). If too many connection errors arise, TLS now automatically falls back to version 1.2 by setting an internal flag which can be manually cleared with [[#ClearTls12FallbackFlag]].
 
[17.0.0+] ApiVersion is now 4.
 
{| class="wikitable" border="1"
|-
! Bits
! Description
|-
| 0 || Auto
|-
| 3 || TlsV10
|-
| 4 || TlsV11
|-
| 5 || TlsV12
|-
| 6 || [11.0.0+] TlsV13
|-
| 24-31 || [11.0.0+] ApiVersion
|}
 
= DebugOptionType =
This is "nn::ssl::sf::DebugOptionType" or "nn::ssl::DebugOption".
 
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| 0 || AllowDisableVerifyOption
|}
 
= FlushSessionCacheOptionType =
This is "nn::ssl::sf::FlushSessionCacheOptionType" or "nn::ssl::FlushSessionCacheOptionType".
 
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| 0 || SingleHost
|-
| 1 || AllHosts
|}
 
= BuiltInCertificateInfo =
This is "nn::ssl::BuiltInManager::BuiltInCertificateInfo".
 
{| class="wikitable" border="1"
|-
! 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".
 
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| -1
| Invalid
|-
| 0
| Removed
|-
| 1
| EnabledTrusted
|-
| 2
| EnabledNotTrusted
|-
| 3
| Revoked
|}
 
= CaCertificateId =
This is "nn::ssl::CaCertificateId".
 
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| -1 || [3.0.0+] All
|-
| 1 || NintendoCAG3
|-
| 2 || NintendoClass2CAG3
|-
| 3 || [16.0.0+] "Nintendo Root CA G4"
|-
| 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
|-
| 1034 || [10.0.3+] "USERTrust RSA Certification Authority"
|-
| 1035 || [10.1.0+] "ISRG Root X10"
|-
| 1036 || [10.1.0+] "USERTrust ECC Certification Authority"
|-
| 1037 || [10.1.0+] "COMODO RSA Certification Authority"
|-
| 1038 || [10.1.0+] "COMODO ECC Certification Authority"
|-
| 1039 || [11.0.0+] "Amazon Root CA 2"
|-
| 1040 || [11.0.0+] "Amazon Root CA 3"
|-
| 1041 || [11.0.0+] "Amazon Root CA 4"
|-
| 1042 || [11.0.0+] "DigiCert Assured ID Root G3"
|-
| 1043 || [11.0.0+] "DigiCert Global Root G3"
|-
| 1044 || [11.0.0+] "DigiCert Trusted Root G4"
|-
| 1045 || [11.0.0+] "Entrust Root Certification Authority - EC1"
|-
| 1046 || [11.0.0+] "Entrust Root Certification Authority - G4"
|-
| 1047 || [11.0.0+] "GlobalSign ECC Root CA - R4"
|-
| 1048 || [11.0.0+] "GlobalSign ECC Root CA - R5"
|-
| 1049 || [11.0.0+] "GlobalSign ECC Root CA - R6"
|-
| 1050 || [11.0.0+] "GTS Root R1"
|-
| 1051 || [11.0.0+] "GTS Root R2"
|-
| 1052 || [11.0.0+] "GTS Root R3"
|-
| 1053 || [11.0.0+] "GTS Root R4"
|-
| 1054 || [12.0.0+] "Security Communication RootCA"
|-
| 1055 || [15.0.0+] "GlobalSign Root E4"
|-
| 1056 || [15.0.0+] "GlobalSign Root R4"
|-
| 1057 || [15.0.0+] "T-TeleSec GlobalRoot Class 2"
|-
| 1058 || [16.0.0+] "DigiCert TLS ECC P384 Root G5"
|-
| 1059 || [16.0.0+] "DigiCert TLS RSA4096 Root G5"
|-
| 32801 || [20.0.0+] "ssl-rr-01.netdev.ntd.nintendo.com"
|-
| 65536 (0x10000) || [16.0.0+] "Nintendo Temp Root CA G4" (Only in "ssl_TrustedCerts.Ounce.bdf") ([19.0.0+] Removed)
|-
| 32802 || [20.0.0+] "ssl-rr-02.netdev.ntd.nintendo.com"
|-
| 32803 || [20.0.0+] "ssl-rr-03.netdev.ntd.nintendo.com"
|-
| 32804 || [20.0.0+] "ssl-rr-04.netdev.ntd.nintendo.com"
|-
| 32805 || [20.0.0+] "ssl-rr-05.netdev.ntd.nintendo.com"
|-
| 32806 || [20.0.0+] "ssl-rr-06.netdev.ntd.nintendo.com"
|-
| 32807 || [20.0.0+] "ssl-rr-07.netdev.ntd.nintendo.com"
|-
| 32808 || [20.0.0+] "ssl-rr-08.netdev.ntd.nintendo.com"
|-
| 32809 || [20.0.0+] "ssl-rr-09.netdev.ntd.nintendo.com"
|-
| 32810 || [20.0.0+] "ssl-rr-10.netdev.ntd.nintendo.com"
|-
| 32811 || [20.0.0+] "ssl-rr-11.netdev.ntd.nintendo.com"
|-
| 32812 || [20.0.0+] "ssl-rr-12.netdev.ntd.nintendo.com"
|-
| 32813 || [20.0.0+] "ssl-rr-13.netdev.ntd.nintendo.com"
|-
| 32814 || [20.0.0+] "ssl-rr-14.netdev.ntd.nintendo.com"
|-
| 32815 || [20.0.0+] "ssl-rr-15.netdev.ntd.nintendo.com"
|-
| 32816 || [20.0.0+] "ssl-rr-16.netdev.ntd.nintendo.com"
|-
| 32817 || [20.0.0+] "ssl-rr-17.netdev.ntd.nintendo.com"
|-
| 32818 || [20.0.0+] "ssl-rr-18.netdev.ntd.nintendo.com"
|-
| 32819 || [20.0.0+] "ssl-rr-19.netdev.ntd.nintendo.com"
|-
| 32820 || [20.0.0+] "ssl-rr-20.netdev.ntd.nintendo.com"
|-
| 32821 || [20.0.0+] "ssl-rr-21.netdev.ntd.nintendo.com"
|-
| 32822 || [20.0.0+] "ssl-rr-22.netdev.ntd.nintendo.com"
|-
| 32823 || [20.0.0+] "ssl-rr-23.netdev.ntd.nintendo.com"
|-
| 32824 || [20.0.0+] "ssl-rr-24.netdev.ntd.nintendo.com"
|-
| 32825 || [20.0.0+] "ssl-rr-25.netdev.ntd.nintendo.com"
|-
| 32826 || [20.0.0+] "ssl-rr-26.netdev.ntd.nintendo.com"
|-
| 32827 || [20.0.0+] "ssl-rr-27.netdev.ntd.nintendo.com"
|-
| 32828 || [20.0.0+] "ssl-rr-28.netdev.ntd.nintendo.com"
|-
| 32829 || [20.0.0+] "ssl-rr-29.netdev.ntd.nintendo.com"
|-
| 32830 || [20.0.0+] "ssl-rr-30.netdev.ntd.nintendo.com"
|-
| 32831 || [20.0.0+] "ssl-rr-31.netdev.ntd.nintendo.com"
|-
| 32832 || [20.0.0+] "ssl-rr-32.netdev.ntd.nintendo.com"
|-
| 32833 || [20.0.0+] "ssl-rr-33.netdev.ntd.nintendo.com"
|-
| 32834 || [20.0.0+] "ssl-rr-34.netdev.ntd.nintendo.com"
|-
| 32835 || [20.0.0+] "ssl-rr-35.netdev.ntd.nintendo.com"
|-
| 32836 || [20.0.0+] "ssl-rr-36.netdev.ntd.nintendo.com"
|-
| 32837 || [20.0.0+] "ssl-rr-37.netdev.ntd.nintendo.com"
|-
| 32838 || [20.0.0+] "ssl-rr-38.netdev.ntd.nintendo.com"
|-
| 32839 || [20.0.0+] "ssl-rr-39.netdev.ntd.nintendo.com"
|-
| 32840 || [20.0.0+] "ssl-rr-40.netdev.ntd.nintendo.com"
|-
| 32841 || [20.0.0+] "ssl-rr-41.netdev.ntd.nintendo.com"
|-
| 32842 || [20.0.0+] "ssl-rr-42.netdev.ntd.nintendo.com"
|-
| 32843 || [20.0.0+] "ssl-rr-43.netdev.ntd.nintendo.com"
|-
| 32844 || [20.0.0+] "ssl-rr-44.netdev.ntd.nintendo.com"
|-
| 32845 || [20.0.0+] "ssl-rr-45.netdev.ntd.nintendo.com"
|-
| 32846 || [20.0.0+] "ssl-rr-46.netdev.ntd.nintendo.com"
|-
| 32847 || [20.0.0+] "ssl-rr-47.netdev.ntd.nintendo.com"
|-
| 32848 || [20.0.0+] "ssl-rr-48.netdev.ntd.nintendo.com"
|-
| 32849 || [20.0.0+] "ssl-rr-49.netdev.ntd.nintendo.com"
|-
| 32850 || [20.0.0+] "ssl-rr-50.netdev.ntd.nintendo.com"
|-
| 32851 || [20.0.0+] "ssl-rr-51.netdev.ntd.nintendo.com"
|-
| 32852 || [20.0.0+] "ssl-rr-52.netdev.ntd.nintendo.com"
|-
| 32853 || [20.0.0+] "ssl-rr-53.netdev.ntd.nintendo.com"
|-
| 32854 || [20.0.0+] "ssl-rr-54.netdev.ntd.nintendo.com"
|-
| 32855 || [20.0.0+] "ssl-rr-55.netdev.ntd.nintendo.com"
|-
| 32856 || [20.0.0+] "ssl-rr-56.netdev.ntd.nintendo.com"
|-
| 32857 || [20.0.0+] "ssl-rr-57.netdev.ntd.nintendo.com"
|-
| 32858 || [20.0.0+] "ssl-rr-58.netdev.ntd.nintendo.com"
|-
| 32859 || [20.0.0+] "ssl-rr-59.netdev.ntd.nintendo.com"
|-
| 32860 || [20.0.0+] "ssl-rr-60.netdev.ntd.nintendo.com"
|-
| 32861 || [20.0.0+] "ssl-rr-61.netdev.ntd.nintendo.com"
|-
| 32862 || [20.0.0+] "ssl-rr-62.netdev.ntd.nintendo.com"
|-
| 32863 || [20.0.0+] "ssl-rr-63.netdev.ntd.nintendo.com"
|-
| 32864 || [20.0.0+] "ssl-rr-64.netdev.ntd.nintendo.com"
|}
 
= InternalPki =
This is "nn::ssl::sf::InternalPki" or "nn::ssl::Context::InternalPki".
 
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| 0 || None
|-
| 1 || DeviceClientCertDefault
|}
 
An error is thrown by [[#RegisterInternalPki]] when the input value does not match "DeviceClientCertDefault".
 
"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.
 
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| 0 || None
|-
| 1 || CrlImportDateCheckEnable
|}
 
= CertificateFormat =
This is "nn::ssl::sf::CertificateFormat" or "nn::ssl::CertificateFormat".
 
{| class="wikitable" border="1"
|-
! 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.
 
{| class="wikitable" border="1"
|-
! 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 [[#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.
 
= 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).
 
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| 1 || Blocking
|-
| 2 || NonBlocking
|}
 
= PollEvent =
This is "nn::ssl::sf::PollEvent" or "nn::ssl::Connection::PollEvent". This is a bitmask.
 
{| class="wikitable" border="1"
|-
! Bit
! Description
|-
| 0 || Read
|-
| 1 || Write
|-
| 2 || Except
|}
 
= SessionCacheMode =
This is "nn::ssl::sf::SessionCacheMode" or "nn::ssl::Connection::SessionCacheMode".
 
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| 0 || None
|-
| 1 || SessionId
|-
| 2 || SessionTicket
|}
 
= RenegotiationMode =
This is "nn::ssl::sf::RenegotiationMode" or "nn::ssl::Connection::RenegotiationMode".
 
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| 0 || None
|-
| 1 || Secure
|}
 
= OptionType =
This is "nn::ssl::sf::OptionType" or "nn::ssl::Connection::OptionType".
 
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| 0 || DoNotCloseSocket
|-
| 1 || [3.0.0+] GetServerCertChain
|-
| 2 || [5.0.0+] SkipDefaultVerify
|-
| 3 || [9.0.0+] EnableAlpn
|}
 
Or in the case of [[#SetPrivateOption]] which is also "nn::ssl::ConnectionPrivate::PrivateOptionType":
 
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| 1 || [[#SetSessionCacheMode]] will throw an error if the input [[#SessionCacheMode]] is non-zero and this option flag is set.
|-
| 2 || [17.0.0+] This exclusively enables the cipher suite specified in the input u32 passed to [[#SetPrivateOption]] (all other ciphers disabled).
|}
 
This corresponds to bool flags. At the time of [[#ISslConnection]] object creation, all of these fields are cleared (excluding PrivateOptionType val1 above?).
 
"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
! Description
|-
| 0 || NoSupport
|-
| 1 || Negotiated
|-
| 2 || NoOverlap
|-
| 3 || Selected
|-
| 4 || EarlyValue
|}
 
= CipherInfo =
This is "nn::ssl::Connection::CipherInfo". This is a 0x48-byte struct.
 
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x40 || Cipher string
|-
| 0x40 || 0x8 || Protocol version string
|}
 
= KeyAndCertParams =
This is "nn::ssl::ContextPrivate::KeyAndCertParams". This is a 0x58-byte struct.
 
This was added with [16.0.0+].
 
The constructor for this in official sw just clears this struct.
 
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x4 || Must be value 1.
|-
| 0x4 || 0x4 || s32 Key size in bits.
|-
| 0x8 || 0x8 || Public exponent, must be non-zero. Only the low 4-bytes are used.
|-
| 0x10 || 0x40 || CN (Common Name) NUL-terminated string.
|-
| 0x50 || 0x4 || An error is thrown if this is value 0 or >0x3F. The official wrapper code for [[#GeneratePrivateKeyAndCert]] verifies that this matches the output from <code>strnlen(struct+0x10, 0x40)</code>, however the sysmodule version just throws an error if the strnlen output matches 0x40 (as in no NUL-terminator found).
|}
 
= 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]], [[10.1.0]], [[11.0.0]], [[12.0.0]]. See [[#CaCertificateId]] for the ssl_TrustedCerts changes.
 
[10.1.0+] added 3 more fingerprints to "/ssl_CaFingerprints.bdf".
 
[11.0.0+] updated "/ssl_CaFingerprints.bdf" and "/ssl_TrustedCerts.bdf".
 
[12.0.0+] updated "/ssl_TrustedCerts.bdf".
 
[16.0.0+] updated "/ssl_TrustedCerts.bdf" and added "/ssl_TrustedCerts.Ounce.bdf". The latter is identical to the former except that it contains an additional cert. The latter also isn't used in ssl-sysmodule (in the retail build at least).
 
[19.0.0+] "/ssl_TrustedCerts.Ounce.bdf" updated
 
[20.0.0+] "/ssl_TrustedCerts.bdf" updated, "/ssl_TrustedCerts.Ounce.bdf" updated ("/ssl_TrustedCerts.Ounce.bdf" is identical to "/ssl_TrustedCerts.bdf").
 
[[#ISslContext]] automatically uses this CertStore, regardless of the used cmds.
 
These have the following structure:
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x4 || Magic "sslT"
|-
| 0x4 || 0x4 || Total entries
|-
| 0x8 || 0x10*{total entries} || Array entries
|}
 
Array entry structure:
{| class="wikitable" border="1"
|-
! 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 [[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]].


key* below refers to the 3 0x10-byte input blocks passed to this code.
key* below refers to the 3 0x10-byte input blocks passed to this code.
Line 8: Line 1,304:
When actual_size is:
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_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+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.
* 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]]