mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
ssl: Updated params and docs + various improvements. Added sslConnectionGetServerCertDetail and the required structs.
This commit is contained in:
parent
41aefdc5ee
commit
41e90ef8b5
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file fs.h
|
||||
* @brief SSL service IPC wrapper.
|
||||
* @brief SSL service IPC wrapper, for using client-mode TLS. See also: https://switchbrew.org/wiki/SSL_services
|
||||
* @author yellows8
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
@ -87,7 +87,7 @@ typedef enum {
|
||||
|
||||
/// InternalPki
|
||||
typedef enum {
|
||||
SslInternalPki_DeviceClientCertDefault = 1, ///< DeviceClientCertDefault
|
||||
SslInternalPki_DeviceClientCertDefault = 1, ///< DeviceClientCertDefault. Enables using the DeviceCert and the CertStore.
|
||||
} SslInternalPki;
|
||||
|
||||
/// ContextOption
|
||||
@ -136,7 +136,7 @@ typedef enum {
|
||||
/// OptionType. The default bool flags value for these at the time of \ref sslContextCreateConnection is cleared.
|
||||
typedef enum {
|
||||
SslOptionType_DoNotCloseSocket = 0, ///< DoNotCloseSocket. See \ref sslConnectionSetSocketDescriptor. This is only available if \ref sslConnectionSetSocketDescriptor wasn't used yet.
|
||||
SslOptionType_GetServerCertChain = 1, ///< [3.0.0+] GetServerCertChain
|
||||
SslOptionType_GetServerCertChain = 1, ///< [3.0.0+] GetServerCertChain. See \ref sslConnectionDoHandshake.
|
||||
SslOptionType_SkipDefaultVerify = 2, ///< [5.0.0+] SkipDefaultVerify. Checked by \ref sslConnectionSetVerifyOption, see \ref SslVerifyOption.
|
||||
SslOptionType_EnableAlpn = 3, ///< [9.0.0+] EnableAlpn. Only available with \ref sslConnectionSetOption. \ref sslConnectionSetSocketDescriptor should have been used prior to this - this will optionally use state setup by that, without throwing an error if that cmd wasn't used.
|
||||
} SslOptionType;
|
||||
@ -168,6 +168,19 @@ typedef struct {
|
||||
u8 *cert_data; ///< CertificateData (converted from an offset to a ptr), in DER format.
|
||||
} SslBuiltInCertificateInfo;
|
||||
|
||||
/// SslServerCertDetailHeader
|
||||
typedef struct {
|
||||
u64 magicnum; ///< Magicnum.
|
||||
u32 cert_total; ///< Total certs.
|
||||
u32 pad; ///< Padding.
|
||||
} SslServerCertDetailHeader;
|
||||
|
||||
/// SslServerCertDetailEntry
|
||||
typedef struct {
|
||||
u32 size; ///< Size.
|
||||
u32 offset; ///< Offset.
|
||||
} SslServerCertDetailEntry;
|
||||
|
||||
/// CipherInfo
|
||||
typedef struct {
|
||||
char cipher[0x40]; ///< Cipher string.
|
||||
@ -292,20 +305,20 @@ Result sslContextGetConnectionCount(SslContext *c, u32 *out);
|
||||
* @param[in] buffer Input buffer, must not be NULL.
|
||||
* @param[in] size Input buffer size.
|
||||
* @param[in] format \ref SslCertificateFormat
|
||||
* @param[out] id Output Id.
|
||||
* @param[out] id Output Id. Optional, can be NULL.
|
||||
*/
|
||||
Result sslContextImportServerPki(SslContext *c, const void* buffer, u32 size, SslCertificateFormat format, u64 *id);
|
||||
|
||||
/**
|
||||
* @brief ImportClientPki
|
||||
* @param c \ref SslContext
|
||||
* @param[in] buf0 First input buffer, must not be NULL.
|
||||
* @param[in] size0 First input buffer size.
|
||||
* @param[in] buf1 Second input buffer, this can only be NULL if size1 is 0.
|
||||
* @param[in] size1 Second input buffer size, this can only be 0 if buf1 is NULL.
|
||||
* @param[out] id Output Id.
|
||||
* @param[in] pkcs12 PKCS#12 input buffer, must not be NULL.
|
||||
* @param[in] pkcs12_size pkcs12 buffer size.
|
||||
* @param[in] pw ASCII password string buffer, this can only be NULL if pw_size is 0. This will be internally copied to another buffer which was allocated with size=pw_size+1, for NUL-termination.
|
||||
* @param[in] pw_size Password buffer size, this can only be 0 if pw is NULL.
|
||||
* @param[out] id Output Id. Optional, can be NULL.
|
||||
*/
|
||||
Result sslContextImportClientPki(SslContext *c, const void* buf0, u32 size0, const void* buf1, u32 size1, u64 *id);
|
||||
Result sslContextImportClientPki(SslContext *c, const void* pkcs12, u32 pkcs12_size, const char *pw, u32 pw_size, u64 *id);
|
||||
|
||||
/**
|
||||
* @brief Remove the specified *Pki, or on [3.0.0+] Crl.
|
||||
@ -318,7 +331,7 @@ Result sslContextRemovePki(SslContext *c, u64 id);
|
||||
* @brief RegisterInternalPki
|
||||
* @param c \ref SslContext
|
||||
* @param[in] internal_pki \ref SslInternalPki
|
||||
* @param[out] id Output Id.
|
||||
* @param[out] id Output Id. Optional, can be NULL.
|
||||
*/
|
||||
Result sslContextRegisterInternalPki(SslContext *c, SslInternalPki internal_pki, u64 *id);
|
||||
|
||||
@ -328,7 +341,7 @@ Result sslContextRegisterInternalPki(SslContext *c, SslInternalPki internal_pki,
|
||||
* @param[in] str Input string.
|
||||
* @param[in] str_bufsize String buffer size, excluding NUL-terminator (must not match the string length). Hence, this should be actual_bufsize-1. This must not be >0xff.
|
||||
*/
|
||||
Result sslContextAddPolicyOid(SslContext *c, const char* str, u32 str_bufsize);
|
||||
Result sslContextAddPolicyOid(SslContext *c, const char *str, u32 str_bufsize);
|
||||
|
||||
/**
|
||||
* @brief ImportCrl
|
||||
@ -336,7 +349,7 @@ Result sslContextAddPolicyOid(SslContext *c, const char* str, u32 str_bufsize);
|
||||
* @param c \ref SslContext
|
||||
* @param[in] buffer Input buffer, must not be NULL.
|
||||
* @param[in] size Input buffer size.
|
||||
* @param[out] id Output Id.
|
||||
* @param[out] id Output Id. Optional, can be NULL.
|
||||
*/
|
||||
Result sslContextImportCrl(SslContext *c, const void* buffer, u32 size, u64 *id);
|
||||
|
||||
@ -399,7 +412,7 @@ Result sslConnectionGetSocketDescriptor(SslConnection *c, int *sockfd);
|
||||
* @param[in] str_bufsize String buffer size, must be large enough for the entire output string.
|
||||
* @param[out] out Output string length.
|
||||
*/
|
||||
Result sslConnectionGetHostName(SslConnection *c, char* str, u32 str_bufsize, u32 *out);
|
||||
Result sslConnectionGetHostName(SslConnection *c, char *str, u32 str_bufsize, u32 *out);
|
||||
|
||||
/**
|
||||
* @brief GetVerifyOption
|
||||
@ -421,12 +434,22 @@ Result sslConnectionGetIoMode(SslConnection *c, SslIoMode *out);
|
||||
* @note \ref sslConnectionSetHostName must have been used previously with a non-empty string when ::SslVerifyOption_HostName is set.
|
||||
* @note The DoHandshakeGetServerCert cmd is only used if both server_certbuf/server_certbuf_size are set, otherwise the DoHandshake cmd is used (in which case out0/out1 will be left at value 0).
|
||||
* @param c \ref SslConnection
|
||||
* @param[out] out0 Optional first output value, can be NULL.
|
||||
* @param[out] out1 Optional second output value, can be NULL.
|
||||
* @param[out] server_certbuf Optional output server cert buffer, can be NULL.
|
||||
* @param[out] out_size Total data size which was written to server_certbuf. Optional, can be NULL.
|
||||
* @param[out] total_certs Total certs which were written to server_certbuf, can be NULL.
|
||||
* @param[out] server_certbuf Optional output server cert buffer, can be NULL. Normally this just contains the server cert DER, however with ::SslOptionType_GetServerCertChain set this will contain the full chain (\ref sslConnectionGetServerCertDetail can be used to parse that).
|
||||
* @param[in] server_certbuf_size Optional output server cert buffer size, can be 0.
|
||||
*/
|
||||
Result sslConnectionDoHandshake(SslConnection *c, u32 *out0, u32 *out1, void* server_certbuf, u32 server_certbuf_size);
|
||||
Result sslConnectionDoHandshake(SslConnection *c, u32 *out_size, u32 *total_certs, void* server_certbuf, u32 server_certbuf_size);
|
||||
|
||||
/**
|
||||
* @brief Parses the output server_certbuf from \ref sslConnectionDoHandshake where ::SslOptionType_GetServerCertChain is set.
|
||||
* @param[in] certbuf server_certbuf from \ref sslConnectionDoHandshake, must not be NULL.
|
||||
* @param[in] certbuf_size out_size from \ref sslConnectionDoHandshake.
|
||||
* @param[in] cert_index Cert index, must be within the range of certs stored in certbuf.
|
||||
* @param[out] cert Ptr for the ouput DER cert, must not be NULL.
|
||||
* @param[out] cert_size Size for the ouput cert, must not be NULL.
|
||||
*/
|
||||
Result sslConnectionGetServerCertDetail(const void* certbuf, u32 certbuf_size, u32 cert_index, void** cert, u32 *cert_size);
|
||||
|
||||
/**
|
||||
* @brief Read
|
||||
@ -434,9 +457,9 @@ Result sslConnectionDoHandshake(SslConnection *c, u32 *out0, u32 *out1, void* se
|
||||
* @param c \ref SslConnection
|
||||
* @param[out] buffer Output buffer, must not be NULL.
|
||||
* @param[in] size Output buffer size, must not be 0.
|
||||
* @param[out] out Output value.
|
||||
* @param[out] out_size Actual transferred size.
|
||||
*/
|
||||
Result sslConnectionRead(SslConnection *c, void* buffer, u32 size, u32 *out);
|
||||
Result sslConnectionRead(SslConnection *c, void* buffer, u32 size, u32 *out_size);
|
||||
|
||||
/**
|
||||
* @brief Write
|
||||
@ -444,9 +467,9 @@ Result sslConnectionRead(SslConnection *c, void* buffer, u32 size, u32 *out);
|
||||
* @param c \ref SslConnection
|
||||
* @param[in] buffer Input buffer, must not be NULL.
|
||||
* @param[in] size Input buffer size, must not be 0.
|
||||
* @param[out] out Output value.
|
||||
* @param[out] out_size Actual transferred size.
|
||||
*/
|
||||
Result sslConnectionWrite(SslConnection *c, const void* buffer, u32 size, u32 *out);
|
||||
Result sslConnectionWrite(SslConnection *c, const void* buffer, u32 size, u32 *out_size);
|
||||
|
||||
/**
|
||||
* @brief Pending
|
||||
@ -462,9 +485,9 @@ Result sslConnectionPending(SslConnection *c, s32 *out);
|
||||
* @param c \ref SslConnection
|
||||
* @param[out] buffer Output buffer, must not be NULL.
|
||||
* @param[in] size Output buffer size, must not be 0.
|
||||
* @param[out] out Output value.
|
||||
* @param[out] out_size Output size.
|
||||
*/
|
||||
Result sslConnectionPeek(SslConnection *c, void* buffer, u32 size, u32 *out);
|
||||
Result sslConnectionPeek(SslConnection *c, void* buffer, u32 size, u32 *out_size);
|
||||
|
||||
/**
|
||||
* @brief Poll
|
||||
@ -568,19 +591,21 @@ Result sslConnectionGetCipherInfo(SslConnection *c, SslCipherInfo *out);
|
||||
* @brief SetNextAlpnProto
|
||||
* @note Only available on [9.0.0+].
|
||||
* @note \ref sslConnectionSetSocketDescriptor must have been used prior to this successfully.
|
||||
* @note ::SslOptionType_EnableAlpn should be set at the time of using \ref sslConnectionDoHandshake, otherwise using this cmd will have no affect.
|
||||
* @param c \ref SslConnection
|
||||
* @param[in] buffer Input buffer, must not be NULL.
|
||||
* @param[in] size Input buffer size, must not be 0. Must be at least 0x2.
|
||||
*/
|
||||
Result sslConnectionSetNextAlpnProto(SslConnection *c, const u8* buffer, u32 size);
|
||||
Result sslConnectionSetNextAlpnProto(SslConnection *c, const u8 *buffer, u32 size);
|
||||
|
||||
/**
|
||||
* @brief GetNextAlpnProto
|
||||
* @note Only available on [9.0.0+].
|
||||
* @note \ref sslConnectionSetSocketDescriptor must have been used prior to this successfully.
|
||||
* @note The output will be all-zero/empty if not available - such as when this was used before \ref sslConnectionDoHandshake.
|
||||
* @param c \ref SslConnection
|
||||
* @param[out] state \ref SslAlpnProtoState
|
||||
* @param[out] out Output value.
|
||||
* @param[out] out Output string length.
|
||||
* @param[out] buffer Output buffer, must not be NULL.
|
||||
* @param[in] size Output buffer size, must not be 0.
|
||||
*/
|
||||
|
@ -378,11 +378,11 @@ Result sslContextImportServerPki(SslContext *c, const void* buffer, u32 size, Ss
|
||||
);
|
||||
}
|
||||
|
||||
Result sslContextImportClientPki(SslContext *c, const void* buf0, u32 size0, const void* buf1, u32 size1, u64 *id) {
|
||||
Result sslContextImportClientPki(SslContext *c, const void* pkcs12, u32 pkcs12_size, const char *pw, u32 pw_size, u64 *id) {
|
||||
if (!serviceIsActive(&c->s))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
if (buf0==NULL || (buf1==NULL && size1) || (buf1!=NULL && !size1))
|
||||
if (pkcs12==NULL || (pw==NULL && pw_size) || (pw!=NULL && !pw_size))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||
|
||||
return _sslObjectDispatchOut(&c->s, 5, *id,
|
||||
@ -391,8 +391,8 @@ Result sslContextImportClientPki(SslContext *c, const void* buf0, u32 size0, con
|
||||
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
|
||||
},
|
||||
.buffers = {
|
||||
{ buf0, size0 },
|
||||
{ buf1, size1 },
|
||||
{ pkcs12, pkcs12_size },
|
||||
{ pw, pw_size },
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -429,7 +429,7 @@ Result sslContextRegisterInternalPki(SslContext *c, SslInternalPki internal_pki,
|
||||
return _sslObjectDispatchInOut(&c->s, 8, tmp, *id);
|
||||
}
|
||||
|
||||
Result sslContextAddPolicyOid(SslContext *c, const char* str, u32 str_bufsize) {
|
||||
Result sslContextAddPolicyOid(SslContext *c, const char *str, u32 str_bufsize) {
|
||||
if (!serviceIsActive(&c->s))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
@ -468,7 +468,7 @@ Result sslConnectionSetSocketDescriptor(SslConnection *c, int sockfd, int *out_s
|
||||
return _sslObjectDispatchInOut(&c->s, 0, sockfd, *out_sockfd);
|
||||
}
|
||||
|
||||
Result sslConnectionSetHostName(SslConnection *c, const char* str, u32 str_bufsize) {
|
||||
Result sslConnectionSetHostName(SslConnection *c, const char *str, u32 str_bufsize) {
|
||||
if (!serviceIsActive(&c->s))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
@ -499,7 +499,7 @@ Result sslConnectionGetSocketDescriptor(SslConnection *c, int *sockfd) {
|
||||
return _sslCmdNoInOutU32(&c->s, (u32*)sockfd, 4);
|
||||
}
|
||||
|
||||
Result sslConnectionGetHostName(SslConnection *c, char* str, u32 str_bufsize, u32 *out) {
|
||||
Result sslConnectionGetHostName(SslConnection *c, char *str, u32 str_bufsize, u32 *out) {
|
||||
if (!serviceIsActive(&c->s))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
@ -526,37 +526,59 @@ Result sslConnectionGetIoMode(SslConnection *c, SslIoMode *out) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result sslConnectionDoHandshake(SslConnection *c, u32 *out0, u32 *out1, void* server_certbuf, u32 server_certbuf_size) {
|
||||
Result sslConnectionDoHandshake(SslConnection *c, u32 *out_size, u32 *total_certs, void* server_certbuf, u32 server_certbuf_size) {
|
||||
if (!serviceIsActive(&c->s))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
if (out0) *out0 = 0;
|
||||
if (out1) *out1 = 0;
|
||||
if (out_size) *out_size = 0;
|
||||
if (total_certs) *total_certs = 0;
|
||||
|
||||
if (server_certbuf==NULL || !server_certbuf_size)
|
||||
return _sslCmdNoIO(&c->s, 8); // DoHandshake
|
||||
|
||||
return _sslCmdNoInOutBufTwoOutU32s(&c->s, out0, out1, server_certbuf, server_certbuf_size, 9); // DoHandshakeGetServerCert
|
||||
return _sslCmdNoInOutBufTwoOutU32s(&c->s, out_size, total_certs, server_certbuf, server_certbuf_size, 9); // DoHandshakeGetServerCert
|
||||
}
|
||||
|
||||
Result sslConnectionRead(SslConnection *c, void* buffer, u32 size, u32 *out) {
|
||||
Result sslConnectionGetServerCertDetail(const void* certbuf, u32 certbuf_size, u32 cert_index, void** cert, u32 *cert_size) {
|
||||
if (certbuf==NULL || cert==NULL || cert_size==NULL || certbuf_size < sizeof(SslServerCertDetailHeader) + cert_index*sizeof(SslServerCertDetailEntry))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||
|
||||
// sdknso doesn't have a certbuf_size param for this. sdknso also uses a struct for output, but that just contains a size/addr anyway.
|
||||
|
||||
SslServerCertDetailHeader *hdr = (SslServerCertDetailHeader*)certbuf;
|
||||
if (hdr->magicnum != 0x4E4D684374726543 || hdr->cert_total <= cert_index) // "CertChMN"
|
||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||
|
||||
SslServerCertDetailEntry *entry = (SslServerCertDetailEntry*)(++hdr);
|
||||
entry+= cert_index;
|
||||
|
||||
if (certbuf_size <= entry->offset || certbuf_size < entry->size || certbuf_size < entry->offset + entry->size)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||
|
||||
*cert = (void*)certbuf + entry->offset;
|
||||
*cert_size = entry->size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result sslConnectionRead(SslConnection *c, void* buffer, u32 size, u32 *out_size) {
|
||||
if (!serviceIsActive(&c->s))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
if (buffer==NULL || !size)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||
|
||||
return _sslCmdOutBufOutU32(&c->s, buffer, size, out, 10);
|
||||
return _sslCmdOutBufOutU32(&c->s, buffer, size, out_size, 10);
|
||||
}
|
||||
|
||||
Result sslConnectionWrite(SslConnection *c, const void* buffer, u32 size, u32 *out) {
|
||||
Result sslConnectionWrite(SslConnection *c, const void* buffer, u32 size, u32 *out_size) {
|
||||
if (!serviceIsActive(&c->s))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
if (buffer==NULL || !size)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||
|
||||
return _sslCmdInBufOutU32(&c->s, buffer, size, out, 11);
|
||||
return _sslCmdInBufOutU32(&c->s, buffer, size, out_size, 11);
|
||||
}
|
||||
|
||||
Result sslConnectionPending(SslConnection *c, s32 *out) {
|
||||
@ -566,14 +588,14 @@ Result sslConnectionPending(SslConnection *c, s32 *out) {
|
||||
return _sslCmdNoInOutU32(&c->s, (u32*)out, 12);
|
||||
}
|
||||
|
||||
Result sslConnectionPeek(SslConnection *c, void* buffer, u32 size, u32 *out) {
|
||||
Result sslConnectionPeek(SslConnection *c, void* buffer, u32 size, u32 *out_size) {
|
||||
if (!serviceIsActive(&c->s))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
if (buffer==NULL || !size)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||
|
||||
return _sslCmdOutBufOutU32(&c->s, buffer, size, out, 13);
|
||||
return _sslCmdOutBufOutU32(&c->s, buffer, size, out_size, 13);
|
||||
}
|
||||
|
||||
Result sslConnectionPoll(SslConnection *c, u32 in_pollevent, u32 *out_pollevent, u32 timeout) {
|
||||
@ -697,7 +719,7 @@ Result sslConnectionGetCipherInfo(SslConnection *c, SslCipherInfo *out) {
|
||||
);
|
||||
}
|
||||
|
||||
Result sslConnectionSetNextAlpnProto(SslConnection *c, const u8* buffer, u32 size) {
|
||||
Result sslConnectionSetNextAlpnProto(SslConnection *c, const u8 *buffer, u32 size) {
|
||||
if (!serviceIsActive(&c->s))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user