Toward safety and security in FACE components: High assurance with portability
The FACE [Future Airborne Capability Environment] approach is a joint government-industry software standard and business strategy for acquisition of affordable software systems that promotes innovation and rapid integration of portable capabilities across global defense programs. FACE - originally avionics-focused only, but has now broadened to encompass a wide catalog of applications for use across the entire spectrum of real-time systems - does not directly address issues of quality or fitness for purpose. Because these traits are obviously important in practice, the natural question for component developers is how to meet both the explicit FACE objective of portability and any domain-specific requirements for software reliability, safety, and security. Part of the answer is to choose appropriate software-development technologies and language(s).
The FACE Technical Standard is an open standard produced by government, industry, and academia members of The Open Group FACE Consortium. (Available for download at https://publications.opengroup.org/c17c/.) It defines a Reference Architecture (Figure 1), open interfaces, and a common data architecture to facilitate intercomponent communication. The current version of the standard is Edition 3.0, while several older editions (2.0, 2.1, and 2.1.1) remain in use and supported.
The FACE Reference Architecture comprises five segments, each with a defining set of requirements:
- Operating System Segment (OSS). The OSS is the software foundation for the other FACE segments and supplies services for partitioning, process/thread management, and memory management. It may also include functionality such as health monitoring, fault management, and life cycle management.
- Input/Output Services Segment (IOSS). The IOSS provides a standard interface between PSSS units of conformance (UoCs) and the IO devices supplied for a given platform.
- Platform-Specific Services Segment (PSSS). The PSSS comprises device services, common services (e.g., logging or device protocol mediation), and graphics services. These supply a standard interface between the Portable Component Segment (PCS) UoCs and the IOSS.
- Transport Services Segment (TSS). The TSS supplies communication services for UoCs from other segments, including distribution, routing, state persistence, and data conversion.
- Portable Components Segment (PCS). A PCS UoC supplies specific application functionality and uses only the TSS Interface for data communication and uses only the OSS Interface for OS support.
A component that meets the requirements for a given segment is referred to as a “unit of conformance” with respect to that segment. The FACE Conformance Program defines the processes to verify, certify, and provide formal recognition that registered software conforms to the FACE Technical Standard and specifies policies and procedures for demonstrating conformance to the requirements for the various segments.
The OSS and its interface
The foundation of the FACE Reference Architecture is the OSS (Figure 2), which provides a standard interface to the other segments through ARINC 653 and POSIX application programming interfaces (APIs). Programming language runtime support libraries are considered to be part of the OSS when (as is typically the case) the interface to their services is through language syntax rather than FACE APIs.
A programming language runtime thus differs from the other OSS components in a critical way. Rather than being specified by an API – which would be overly constraining, given the differences across compiler implementations – the interface to the run time is defined by a set of language features (a so-called capability set). The implementation of the run time may or may not realize the capability set’s functionality through calls on the FACE APIs. More generally, the interface between the OSS components and the lower-level services needed in their implementation (the so-called bottom-side interfaces) are not defined or constrained by the FACE technical standard.
FACE-conformant components can be deployed in a variety of contexts with differing requirements for safety and/or security. The FACE Technical Standard therefore defines a set of profiles for the OSS interface. In increasing order of generality, they are:
- Security: This is a minimal interface, designed to support applications with high security-assurance requirements. It guarantees real-time deterministic behavior and requires time and space partitioning.
- Safety: This consists of two subprofiles, Safety Base and Safety Extended. These are aimed at systems with safety certification requirements. The two profiles guarantee real-time deterministic behavior and recommend but do not require time and space partitioning.
- General-purpose: In this profile, real-time determinism is not guaranteed, and time/space partitioning is optional. The general-purpose profile is geared toward components at low levels of safety/security assurance.
The choice of programming language(s) is one of the fundamental decisions during system design. The source code is the artifact that is developed, verified, and maintained, and it is also the subject of much of the analysis required for safety or security certification. Although in principle almost any programming language could be used to develop high-assurance software, in practice software life cycle costs are reduced when the chosen language has been explicitly designed for reliability, safety, and security. The FACE Technical Standard specifically cites four candidate languages – C, C++, Ada, and Java – and, of these, Ada best satisfies this criterion. Especially suitable for components that need to conform to the security profile or one of the safety profiles, Ada avoids C and C++ vulnerabilities such as buffer overrun, and it also avoids Java’s nondeterminism issues (garbage collection, thread semantics).
Ada helps meet high-assurance requirements through its support for sound software-engineering practice, compile-time checks that enforce type safety, and runtime checks that enforce dynamic constraints such as array index bounds and scalar ranges. A deterministic subset of Ada concurrency features – known as the Ravenscar profile – allows Ada concurrency to be used in applications that need to meet high-assurance certification requirements such as DO-178B or DO-178C for airborne software.
Portability is the driving force behind the FACE approach and was also a key goal for Ada. The challenge for a programming language is to define the semantics in a platform-independent manner without sacrificing runtime efficiency. Ada achieves this in several ways. First, it provides a high-level model for concurrency (tasking), memory management, and exception handling, with standard semantics across all platforms that can be mapped to the most efficient services provided by the target system. This is entirely consistent with the treatment of language run times in the FACE reference architecture. With Ada, the developer can also express the logical properties of a type (such as integer range, floating-point precision, record fields/types) in a machine-independent fashion, which the compiler can then map to an efficient underlying representation. The physical representation of data structures (layout, alignment, addresses) is sometimes specified by system requirements, and Ada enables this to be defined in the program logic but separated from target-dependent properties for ease of maintenance.
The rationale underlying the provision of OSS profiles – higher assurance levels imply restrictions on generality – also applies to the programming language. The FACE Technical Standard thus defines corresponding sets of restrictions (capability sets) for C, C++, Ada, and Java. The security and safety capability sets specify subsets of runtime functionality and also restrict other general-purpose features that could be problematic at higher assurance levels.
Edition 3.0 of the FACE Technical Standard defines two general-purpose capability sets for Ada: one for Ada 95, which allows most of the language, and the other for Ada 2012. The Ada 2012 general-purpose capability set contains the Ada 95 set and several Ada 2012 features, although contract-based programming (illustrated in Figure 3) is not yet included. The safety and security capability sets for Ada are defined only for Ada 95, and not (yet) for Ada 2012. These capability sets introduce further restrictions such as limiting concurrency features to those allowed by the Ravenscar profile.
The Ada 2012 standard introduced significant functionality, in particular for “contract-based programming,” which directly supports safety and security and is enabled via coding standards used by major defense system providers. Ada 2012 is implemented on a wide range of target platforms, including real-time operating systems (RTOSs) for which OSS conformance has been certified or is being planned. In light of Ada 2012’s maturity and benefits, contract-based programming and other Ada 2012 features are under consideration to be added to Ada’s security and safety capability sets when the FACE Technical Standard is updated.
FACE: Moving forward
An organization seeking to develop FACE-conformant components needs to adhere to the FACE APIs in the interest of portability but has considerable flexibility in the choice of development and verification technologies. For applications where high assurance is required, Ada offers intrinsic benefits and has development environments that can support all versions of the language standard. AdaCore’s GNAT Pro, for example, implements Ada’s safety-extended capability set and will support Ada capability sets in future FACE versions as they evolve. GNAT Pro’s Ravenscar run time is available for the safety profiles implemented by Wind River’s VxWorks 653 and Lynx Software Technology’s LynxOS-178 RTOSs for several versions of the FACE Technical Standard, allowing developers to design portable concurrent programs with safe and deterministic behavior.
Ada has a long history of successful usage in military and commercial avionics projects and other critical applications, and FACE component developers can exploit Ada’s benefits to produce portable code at the relevant level of assurance. Reuse for Ada has not simply been at the level of small libraries; avionics developers have ported nearly complete line replaceable units (LRUs) and functional application modules across different host development environments and different targets. Ada was designed and is being used for exactly the kinds of applications and environments that the FACE approach is targeting, both in new projects and upgrades of existing systems. Developers can use Ada for the FACE profile (security, safety base, safety extended, general-purpose) that matches their assurance needs.