Pyromaniac

Pyromaniac PRM: AcornSSL

Pyromaniac PRM: AcornSSL

RISC OS PyromaniacAcornSSL

Introduction and Overview

AcornSSL provides a BSD-like socket interface for communication through the TCP/IP protocol stack to resources that require a secure connection. It uses the mbedTLS library for the majority of its implementation; the module itself calls the corresponding mbedTLS functions and wraps them into a set of SWIs that mirror the equivalent calls provided by the Internet module's BSD sockets interface.

At the time of writing, AcornSSL supports all current TLS standards:

  • TLS version 1.0
  • TLS version 1.1
  • TLS version 1.2

The earlier SSL version 2 and 3 standards are considered too insecure and are not supported at all, and TLS version 1.0 is likely to be withdrawn in future. The client SWI interface offers no mechanism to select which protocol version is used; attempting to connect to a server that only offers one of the insecure methods will fail.

Application authors who need a network resource protected by TLS, most commonly for the https: URL scheme handled by AcornHTTP, use AcornSSL either directly through its SWI interface, or indirectly through a higher-level fetcher module that already knows how to drive it. Because untrusted or unexpected certificates may need to be approved by a person before a connection can proceed, AcornSSL also provides a desktop user interface: a small Wimp task that displays a certificate confirmation dialogue whenever a session's server certificate cannot be verified automatically.

Technical Details

Handles and sessions

Every AcornSSL SWI operates on an ssl handle, obtained from SWI AcornSSL_Creat or SWI AcornSSL_CreateSession. This handle is superficially similar to a socket handle from SWI Socket_Creat, but it is not a socket handle and must be treated as an opaque value: it must not be used with the Internet module's socket SWIs, and a socket handle must not be used with the AcornSSL SWIs.

The AcornSSL SWIs are deliberately close analogues of the corresponding socket SWIs, so that code already written against a BSD-like sockets API can be adapted to use secure connections with minimal change. Which SWIs are needed depends on whether an insecure exchange is required before the connection becomes secure. Some protocols need an initial plain-text exchange to negotiate whether, or how, to proceed to a secure connection; others are secure from the first byte:

Secure from the startSecure after negotiation
AcornSSL_CreatSocket_Creat -- get a handle
AcornSSL_ConnectSocket_Connect -- connect to the remote host
(secure dialogue)Socket_Read / Socket_Write -- insecure dialogue
AcornSSL_CreateSession -- associate the handle
AcornSSL_Read / AcornSSL_WriteAcornSSL_Read / AcornSSL_Write -- secure dialogue
AcornSSL_CloseAcornSSL_Close then Socket_Close

SWI AcornSSL_CreateSession is the SWI used to upgrade an existing, already-open socket (typically one obtained from SWI Socket_Creat and already connected) into a secure session, without needing to close and reopen the connection.

Data structures

Several AcornSSL SWIs operate on fixed-format data blocks that are shared with the Internet module's socket SWIs. These are documented here so that the individual SWI definitions below can refer to them, rather than repeating the field layout at every point of use.

Address structure

SWI AcornSSL_Connect, SWI AcornSSL_Getpeername, and SWI AcornSSL_Getsockname all use the same address structure as the corresponding Socket_ SWIs. For the IPv4 sessions AcornSSL currently supports, this is the 16-byte sockaddr_in block:

OffsetSizeFieldContents
01sin_lenLength of the structure, in bytes (16)
11sin_familyAF_INET (2); no other address family is currently supported
22sin_portPort number, in network byte order
44sin_addrIPv4 address, in network byte order
88sin_zeroReserved, must be zero

On SWI AcornSSL_Connect the caller supplies this structure to describe the remote host to connect to. On SWI AcornSSL_Getpeername and SWI AcornSSL_Getsockname the SWI fills it in to describe the remote or local end of the connection respectively.

Status structure

SWI AcornSSL_Stat fills in the same struct stat block as SWI Socket_Stat, defined in C:TCPIPLibs.sys.h.stat. Because this structure was designed to describe files rather than sockets, most of its fields are not meaningful for an ssl handle and should be ignored; only st_mode, which identifies the handle as a socket, and st_blksize, which gives a hint of the optimal I/O size for the connection, are populated with useful values.

OffsetSizeFieldContents
02st_devUndefined
44st_inoUndefined
82st_modeFile type and mode; S_IFSOCK is set to identify the handle as a socket
102st_nlinkUndefined
122st_uidUndefined
142st_gidUndefined
162st_rdevUndefined
204st_sizeUndefined
248st_atimespecUndefined
328st_mtimespecUndefined
408st_ctimespecUndefined
484st_blksizeOptimal block size for reads and writes on this connection
524st_blocksUndefined
564st_flagsUndefined
604st_genUndefined

The buffer passed in R1 must be large enough to hold the whole structure (64 bytes).

Blocking versus non-blocking operation

select()

An application that wants to use select() semantics cannot select directly on an ssl handle. The semantics of select() require a set of bitmaps with bits relating to each socket number, but ssl handles are opaque values that do not contain small incrementing integers, so the FD_SET, FD_CLR, and FD_ISSET macros cannot be used with them.

If an application's structure requires select(), the recommended approach is to create the underlying socket with SWI Socket_Creat and then associate it with an ssl handle using SWI AcornSSL_CreateSession. Because SWI Socket_Creat does return small incrementing socket numbers, those can be used with select() as normal.

A successful select() does not necessarily mean application data is available. Data that appears ready for reading or writing on the underlying socket may in fact be the security library handling an alert, or updating a session ticket, so a successful select() can still be followed by SWI AcornSSL_Recv or SWI AcornSSL_Send returning nothing.

FIONBIO

SWI AcornSSL_Ioctl can be used to mark an ssl handle as non-blocking, by applying the FIONBIO command with a pointer to an integer value of 1 (to enable non-blocking operation) or 0 (to disable it).

If this is done before connecting, the connect operation also becomes non-blocking and returns EINPROGRESS. Since it is not possible to select() on an ssl handle directly, there is no convenient way to discover when such a connection becomes ready for writing. The simplest workaround is to leave the connection as blocking (the default) until after it has connected, and only then use FIONBIO before performing reads and writes. Alternatively, an application may proceed regardless and expect ENOTCONN from any SWI that needs an established connection: SWI AcornSSL_Recv, SWI AcornSSL_Send, SWI AcornSSL_Read, SWI AcornSSL_Write, and SWI AcornSSL_Getpeername.

Extension socket options

A session can be configured by calling SWI AcornSSL_Getsockopt or SWI AcornSSL_Setsockopt after SWI AcornSSL_Creat or SWI AcornSSL_CreateSession, but before SWI AcornSSL_Connect, to alter parameters relating to that specific session. Two extension options are defined, in addition to the standard socket options recognised by the Internet module:

OptionMeaning
11E0 SO_ACORNSSL_HOSTNAME -- associates the expected name of the remote host with the current session. Because name resolution is performed by the client, and a single peer can present several alias names, there would otherwise be no way to cross-check, from the IP address alone, whether the certificate presented by the server was issued to the expected name. The expected host name is also required if the server administrator has enabled SNI (Server Name Identification); without it no name is sent during handshaking, and the connection is likely to be refused. A name pointer of NULL (the default, if this option is never set) skips checking the peer's name and does not send an expected name while handshaking.

Unlike most options, the value of this option is itself a pointer, so it does not follow the usual pattern of R3 pointing at a buffer that holds the value:

  • To set the option, R3 (optval) must itself be the address of a nul-terminated host name string -- not the address of a variable that holds that address. AcornSSL does not dereference R3 an extra time; it uses the value of R3 directly as a const char *. R4 (optlen) is passed by value and must be 4 (the size of a pointer); it is not the length of the host name string.
  • To read the option back, R3 (optval) is the address of a 4-byte word; AcornSSL writes the address of its own internally-held copy of the host name into that word (so a second level of indirection is needed to reach the string itself: R3 points to the word, and the word holds the string's address). R4 (optlen) is a pointer to a word that must hold 4 on entry; AcornSSL does not alter it.

11E1 SO_ACORNSSL_PROMPTTIME -- defines how long, in centiseconds, the certificate confirmation dialogue will wait for a response if a certificate is flagged as bad. A value of zero displays no prompt and fails the connection immediately. To set the option, optval is a pointer to the value in centiseconds and optlen is 4 (the size of an integer); to read it back, optval is a pointer to receive the integer, and optlen is a pointer to an integer holding 4.

Loading the module

Application authors who want to be sure the AcornSSL SWIs are available should use *RMEnsure in the usual manner, for example:

RMEnsure AcornSSL 1.23 RMLoad System:Modules.Network.URL.AcornSSL
RMEnsure AcornSSL 1.23 Error Application requires AcornSSL 1.23 or later

A more comprehensive series of *RMEnsure commands would be needed if an earlier AcornSSL is already loaded with active clients, because loading a second copy of the module would end those sessions. When tracking security enhancements it can be assumed that the latest available version is always preferable, even at the expense of terminating existing sessions.

The System: path variable should be used, as shown above, rather than a reference to a specific RISC OS version's directory inside !System; the module may in future be shipped with builds tailored to different RISC OS versions.

SWI Calls

AcornSSL's SWIs occupy the chunk based at &50F80. Except where noted, each SWI is a close analogue of the correspondingly named SWI provided by the Internet module for plain BSD sockets, but operating on an ssl handle rather than a socket handle.

AcornSSL_CreatSWI &50F80
Initialises a secure session with a new socket
R0=
Bit(s)NameMeaning
0-7domain Address family, as for SWI Socket_Creat; AF_INET (2) for the IPv4 sessions AcornSSL currently supports
8-31Reserved, must be zero
R1=type, as for SWI Socket_Creat; SOCK_STREAM for a TLS connection
R2=protocol, as for SWI Socket_Creat; normally 0
R0=ssl handle
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Creat, this SWI initialises a new secure session, returning a handle to use with the other AcornSSL SWIs. The handle is not a socket handle and must be treated as opaque.

If a socket handle from SWI Socket_Creat has already been opened and needs to be upgraded to a secure session, use SWI AcornSSL_CreateSession instead.

AcornSSL_IoctlSWI &50F81
Performs miscellaneous socket input/output control
R0=ssl handle
R1= operation, as for SWI Socket_Ioctl:
OperationMeaning
FIONBIOSets or clears non-blocking operation for the ssl handle; intercepted by AcornSSL itself rather than being passed to the underlying socket
(any other)Passed through unchanged to the underlying socket's SWI Socket_Ioctl handling
R2= pointer to argument, dependent on the operation; for FIONBIO this is a pointer to a 4-byte integer that is zero to disable non-blocking operation, or non-zero to enable it
R0=0 for success
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Ioctl. In particular, the FIONBIO operation is used to switch an ssl handle between blocking and non-blocking operation; AcornSSL records this setting on the ssl handle itself, separately from the underlying socket, so that it can apply it consistently to the TLS reads and writes it performs on the caller's behalf.

AcornSSL_ConnectSWI &50F82
Connects the secure session to a remote host
R0=ssl handle
R1=pointer to Address structure, describing the remote host to connect to
R2=size of the address structure, in bytes (16 for an IPv4 address)
R0=0 for success
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Connect.

AcornSSL_ShutdownSWI &50F83
Shuts one or both halves of a connection
R0=ssl handle
R1=direction of shutdown
R0=0 for success
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Shutdown.

AcornSSL_CloseSWI &50F84
Closes a connection
R0=ssl handle
R0=0 for success
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Close. Closing the secure session with this SWI does not close the underlying socket handle when the session was created with SWI AcornSSL_CreateSession; the caller remains responsible for closing that socket with SWI Socket_Close.

AcornSSL_GetsockoptSWI &50F85
Gets a socket option
R0=ssl handle
R1=option level, as for SWI Socket_Getsockopt; the Extension socket options are also recognised at level SOL_SOCKET
R2=option, as for SWI Socket_Getsockopt or one of the Extension socket options
R3=pointer to buffer to receive the option value
R4=pointer to a word holding the size of the buffer at R3; updated on exit to the size actually written, for standard socket options
R0=0 for success
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Getsockopt. As well as the standard socket options, this SWI recognises the Extension socket options described under Technical Details.

For the AcornSSL extension options, R4 is not updated on exit; the caller must set it to 4 on entry, and it is left unchanged. For SO_ACORNSSL_HOSTNAME specifically, R3 does not follow the usual buffer pattern: see the option's own description under Extension socket options for the exact indirection it uses.

AcornSSL_WriteSWI &50F86
Writes data to a secure connection
R0=ssl handle
R1=pointer to data to send
R2=amount of data to send
R0=amount of data written
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Write; equivalent to SWI AcornSSL_Send with flags of 0.

AcornSSL_RecvSWI &50F87
Reads data from a secure connection
R0=ssl handle
R1=pointer to data to receive
R2=size of data buffer
R3= option flags:
Bit(s)NameMeaning
0Reserved, must be zero
1MSG_PEEKReturns the requested data without removing it from the connection, so that a later call re-reads the same data
2-5Reserved, must be zero
6MSG_WAITALLForces this call to wait until the request can be satisfied in full, overriding non-blocking operation set by SWI AcornSSL_Ioctl; ignored if MSG_DONTWAIT is also set
7MSG_DONTWAITForces this call to be non-blocking, overriding blocking operation set by SWI AcornSSL_Ioctl; ignored if MSG_WAITALL is also set
R0=amount of data received
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Recv.

While a secure link is being established, and a certificate exchange is taking place that may require the user to confirm an untrusted certificate, the link's status may be reported as ENOTCONN, so as to match the response the Internet module gives before a link is up.

If MSG_DONTWAIT and MSG_WAITALL are both set, or both clear, the call uses whichever blocking mode was last set with SWI AcornSSL_Ioctl (blocking, unless FIONBIO has been used to enable non-blocking operation).

AcornSSL_CreateSessionSWI &50F88
Initialises a secure session with an existing socket
R0=socket handle from Socket_Creat
R1=
Bit(s)NameMeaning
0-7reason code
ReasonAction
0Creates a new secure session over an existing socket
1Creates a new secure session, reusing the authentication of another session
8-31Reserved, must be zero
R2 - R3=dependent on reason code
R0=ssl handle
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

This SWI performs a similar function to SWI AcornSSL_Creat, but allows the caller to hand over a previously opened socket, so that an insecure exchange over that socket can be followed by a switch to a secure session without closing the connection.

AcornSSL_CreateSession 0NewSWI &50F88
Creates a new secure session over an existing socket
R0=socket handle from Socket_Creat
R1=CreateSession_New (0)
R0=ssl handle
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Creates a new secure session that takes over the given socket handle.

AcornSSL_CreateSession 1ReuseAuthSWI &50F88
Creates a new secure session, reusing the authentication of another session
R0=socket handle from Socket_Creat
R1=CreateSession_ReuseAuth (1)
R2= ssl handle of another secure session already authenticated with the server
R0=ssl handle
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Creates a new secure session that takes over the given socket handle, using the authentication already established by another, already-authenticated secure session to the same server to complete the connection. This avoids the need to re-authenticate, and re-run the certificate confirmation process, for a second connection that the caller already knows to be trusted.

AcornSSL_GetpeernameSWI &50F89
Gets details of the remote host's address
R0=ssl handle
R1=pointer to buffer to receive the Address structure
R2=pointer to a word holding the size of the buffer at R1; updated on exit to the size of the structure written
R0=0 for success
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Getpeername; returns the address of the remote host at the other end of the underlying connection.

AcornSSL_GetsocknameSWI &50F8A
Gets details of the local host's address
R0=ssl handle
R1=pointer to buffer to receive the Address structure
R2=pointer to a word holding the size of the buffer at R1; updated on exit to the size of the structure written
R0=0 for success
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Getsockname; returns the local address in use by the underlying connection.

AcornSSL_SetsockoptSWI &50F8B
Sets a socket option
R0=ssl handle
R1=option level, as for SWI Socket_Setsockopt; the Extension socket options are also recognised at level SOL_SOCKET
R2=option, as for SWI Socket_Setsockopt or one of the Extension socket options
R3=pointer to buffer holding the option value to set, for most options (see below for an exception)
R4=size of the option value, in bytes
R0=0 for success
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Setsockopt. As well as the standard socket options, this SWI recognises the Extension socket options described under Technical Details. Extension options may only be set after SWI AcornSSL_Creat or SWI AcornSSL_CreateSession, and before SWI AcornSSL_Connect.

SO_ACORNSSL_HOSTNAME is an exception to the usual buffer pattern for R3: because the value being set is itself a pointer, R3 must be the address of the host name string directly, not the address of a variable holding that address. See the option's own description under Extension socket options for details.

AcornSSL_StatSWI &50F8C
Reads status information for a socket
R0=ssl handle
R1=pointer to buffer to receive the Status structure (64 bytes)
R0=0 for success
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Stat; fills in the Status structure for the underlying socket of the ssl handle. As with SWI Socket_Stat, most fields of the structure are not meaningful for a socket and should be ignored; only st_mode and st_blksize carry useful information. See Technical Details for the full field layout.

AcornSSL_VersionSWI &50F8D
Reads the module's version number
R0 - R9preserved
R0=100 times the module's version number
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Version.

If extra features are added to AcornSSL in the future, this version number can be read to determine whether the loaded copy of the module is able to support those features.

AcornSSL_ReadSWI &50F8E
Reads data from a secure connection
R0=ssl handle
R1=pointer to data to receive
R2=size of data buffer
R0=amount of data received
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Read; equivalent to SWI AcornSSL_Recv with flags of 0.

AcornSSL_SendSWI &50F8F
Writes data to a secure connection
R0=ssl handle
R1=pointer to data to send
R2=amount of data to send
R3= option flags:
Bit(s)NameMeaning
0-5Reserved, must be zero
6MSG_WAITALLForces this call to wait until the whole request has been sent, overriding non-blocking operation set by SWI AcornSSL_Ioctl; ignored if MSG_DONTWAIT is also set
7MSG_DONTWAITForces this call to be non-blocking, overriding blocking operation set by SWI AcornSSL_Ioctl; ignored if MSG_WAITALL is also set
R0=amount of data written
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

Analogous to SWI Socket_Send.

While a secure link is being established, and a certificate exchange is taking place that may require the user to confirm an untrusted certificate, the link's status may be reported as ENOTCONN, so as to match the response the Internet module gives before a link is up.

If MSG_DONTWAIT and MSG_WAITALL are both set, or both clear, the call uses whichever blocking mode was last set with SWI AcornSSL_Ioctl (blocking, unless FIONBIO has been used to enable non-blocking operation).

AcornSSL_ConfigureSessionSWI &50F90
Reserved; not currently defined or implemented
None
None
Interrupts are undefined
Fast interrupts are undefined
Processor is in undefined mode
Not defined

This SWI number is reserved for future use. AcornSSL does not currently define or implement it, and calling it returns the standard Bad SWI error.

Service Calls

AcornSSL issues Service_URLModule_SSL to communicate important events about its own availability. Client software should not claim this service call.

Service_URLModule_SSLService Call &83E02
Communicates AcornSSL module lifecycle events
R0=
ValueMeaning
0SSL module became available (Service_URLModule_SSL_Started)
1SSL module no longer available (Service_URLModule_SSL_Dying)
R1=&83E02 (Service_URLModule_SSL)
R2=the module's version number multiplied by 100
R0 - R2preserved

AcornSSL issues this service call, with R0 set to 0, when it becomes available, and again, with R0 set to 1, when it is about to become unavailable (for example when it is being re-loaded, or killed). Recipients must preserve all registers and must not claim this service call.

AcornHTTP re-announces AcornSSL's presence by generating this service call itself if AcornHTTP starts after AcornSSL has already announced itself, so that other modules relying on the https: scheme still see the announcement even if their own startup missed the original call.

Commands

*Desktop_AcornSSL
Starts the AcornSSL certificate confirmation desktop task
*Desktop_AcornSSL
None

Starts the Wimp task that displays AcornSSL's certificate confirmation dialogue. This command takes no parameters, and is issued automatically by AcornSSL itself, in response to Service_StartWimp, when the desktop starts; it should not normally be issued directly.

If the task is already running, the command reports an error rather than starting a second copy.

*Desktop_AcornSSL

Certificate Confirmation Dialogue

When AcornSSL cannot fully verify a server's certificate chain against its trusted root certificates, or the certificate presented fails one of its other checks, the connection does not fail outright. Instead, provided the desktop is running and SO_ACORNSSL_PROMPTTIME has not been set to zero for that session, AcornSSL asks the user whether the connection should be allowed to proceed. While this confirmation is pending, and while any handshaking that requires it is in progress, calls such as SWI AcornSSL_Recv and SWI AcornSSL_Send report the connection's status as ENOTCONN.

The certificate confirmation dialogue is presented by a small Wimp task, started automatically as *Desktop_AcornSSL when the desktop starts. This task is separate from the AcornSSL module itself: the module runs the TLS handshake and evaluates the certificate chain in the background, and communicates with the task only to display a dialogue and collect the user's decision.

What the dialogue shows

The dialogue is shown once for each certificate in the chain that needs the user's attention, starting with the certificate presented by the remote server (the subject) and, where the user chooses to inspect it, working back towards the root of trust (the issuer). Each certificate's dialogue shows:

  • the certificate's issuer
  • the certificate's subject
  • the period for which the certificate is valid
  • the certificate's serial number
  • the certificate's signature

Where a check on the certificate has failed, the corresponding field is marked to draw attention to the specific problem: an expired, not-yet-valid, revoked, or otherwise unacceptable validity period; a signature the module could not verify; or an issuer that is not among the trusted roots. The final certificate in the chain is the root; it has no further issuer to inspect, so its dialogue omits the button used to move up the chain.

Responding to the dialogue

For the certificate at the top of the chain (the one the server presented), the dialogue offers three responses:

  • Reject refuses the connection. Rejecting any certificate in the chain rejects the whole chain, and the corresponding SWI call fails.
  • Accept allows the connection to proceed this time only; the same certificate will be queried again on a future connection.
  • Accept always allows the connection to proceed, and records an exception so that the same certificate is accepted automatically in future without prompting again.

Dialogues for certificates further up the chain (the issuers) only offer Accept and Reject, since the decision to trust the chain permanently is made once, at the top level, after the intervening issuers have been reviewed.

Each certificate's dialogue also offers a View certificate button, which writes the certificate to a pipe file in PEM form and opens it in the user's default text viewer, so the certificate's contents can be inspected in detail before a decision is made.

Timing out

SWI AcornSSL_Setsockopt with SO_ACORNSSL_PROMPTTIME controls how long, in centiseconds, a session will wait for the user to respond before the connection attempt fails. A value of zero suppresses the dialogue entirely for that session and fails the connection as soon as the certificate check fails, which is appropriate for background or unattended connections where no user is available to respond.

Error Messages

AcornSSL's own errors are allocated the range &813F20 to &813F3F. These are used for failures that are specific to the module, or that arise from a SWI that has no direct BSD sockets equivalent (such as SWI AcornSSL_CreateSession).

Most errors from the socket-like SWIs are instead mapped onto Unix errors in the DCI4 error range, for maximum compatibility with the BSD sockets API used by the Internet module. The full list of these errors can be found in C:TCPIPLibs.sys.h.errno, and macros to recognise and extract them from a RISC OS error are in C:TCPIPLibs.sys.h.dcistructs. Errors propagated from a component AcornSSL relies on (for example, a ‘File not found’ error while reading a certificate file) are passed back unchanged.

Error_AcornSSL_BadSessionError &813F20
Bad session handle

An ssl handle passed to a SWI does not refer to a currently open session.

Error_AcornSSL_BadCtxError &813F21
Bad context handle

The session's internal mbedTLS context is not in a usable state.

Error_AcornSSL_NoInitError &813F22
Security libraries unable to initialise (reason %0)

The underlying security library failed to initialise; the substituted value gives the mbedTLS reason code.

Error_AcornSSL_NoVerifyLocationsError &813F23
Unable to initialise certificate verification procedures (reason %0)

The certificate verification machinery could not be set up; the substituted value gives the mbedTLS reason code.

Error_AcornSSL_NoRootCAError &813F24
Can't locate root certificate store

The store of trusted root certificates could not be found or read.

Error_AcornSSL_MallocError &813F25
Failed to allocate memory

AcornSSL was unable to allocate memory needed to complete the request.

Error_AcornSSL_SocketErrorError &813F26
Socket error (code %0)

The underlying socket reported an error that could not be mapped onto a Unix error number; the substituted value gives the underlying error code.

Error_AcornSSL_HandshakeErrorError &813F27
Handshake error (state %0)

The TLS handshake failed; the substituted value gives the mbedTLS handshake state at the point of failure.

Error_AcornSSL_ParameterErrorError &813F28
Parameter error (code %0)

A parameter passed to a SWI was invalid; the substituted value gives the mbedTLS error code that identified the problem.

Error_AcornSSL_NoExceptionsError &813F29
Can't locate certificate exceptions

The store of certificate exceptions, recorded when the user chooses Accept always in the certificate confirmation dialogue, could not be found or read.

Examples

Connecting with certificate name checking

This example shows the minimum sequence of calls needed to open a secure connection directly, associating an expected host name with the session so that the peer's certificate is checked against it, in the same way a web browser checks a server's certificate against the name in the URL.

int ssl, err;
const char *hostname = "example.com";

/* Get a handle, and check the peer's name during handshaking */
ssl = call AcornSSL_Creat, get ssl handle;
call AcornSSL_Setsockopt, SO_ACORNSSL_HOSTNAME, hostname, 4;

/* Connect; this may trigger the certificate confirmation dialogue */
err = call AcornSSL_Connect, address, addresslen;

/* Read and write the secure connection as usual */
call AcornSSL_Write, ...;
call AcornSSL_Read, ...;

/* Finished */
call AcornSSL_Close;

Upgrading an existing socket

This example shows a protocol that starts with a plain-text exchange over a socket created with SWI Socket_Creat, and only switches to a secure session partway through the conversation, as is typical for protocols such as STARTTLS-style negotiations.

int sock, ssl;

/* Open and connect an ordinary socket, and talk to it in plain text */
sock = call Socket_Creat, get socket handle;
call Socket_Connect, address, addresslen;
negotiate whether to go secure, in plain text;

/* Hand the socket over to AcornSSL and continue securely */
ssl = call AcornSSL_CreateSession, sock, CreateSession_New;
call AcornSSL_Write, ...;
call AcornSSL_Read, ...;

/* Finished; close the secure session, then the underlying socket */
call AcornSSL_Close;
call Socket_Close, sock;