2 Security Layer

2.1 Introduction

The OSGi Security Layer is an optional layer that underlies the OSGi framework. The layer is based on the Java security architecture. It provides the infrastructure to deploy and manage applications that must run in fine-grained controlled environments.

2.1.1 Essentials

  • Fine-grained - The control of applications running in an OSGi Framework must allow for detailed control of those applications.

  • Manageable - The security layer itself does not define an API to control the applications. The management of the security layer is left to the life cycle layer.

  • Optional - The security layer is optional.

2.2 Security Overview

The Framework security model is based on the Java specification. If security checks are performed, they must be done according to [3] Java Security Architecture. It is assumed that the reader is familiar with this specification. The security layer is optional, see Optional Security.

2.2.1 Code Authentication

The OSGi framework can authenticate code in the following ways:

  • By location

  • By signer

At higher layers there are defined services that can manage the permissions that are associated with the authenticated unit of code. These services are:

  • Permission Admin service - Manages the permission based on full location strings.

  • Conditional Permission Admin service - Manages the permissions based on a comprehensive conditional model, where the conditions can test for location or signer.

For signing, this requires the JAR files to be signed; this is described in Digitally Signed JAR Files.

2.2.2 Optional Security

The Java platform on which the Framework runs must provide the Java Security APIs necessary for Java permissions. On resource-constrained platforms, these Java Security APIs may be stubs that allow the bundle classes to be loaded and executed, but the stubs never actually perform the security checks. The behavior of these stubs must be as follows:

  • checkPermission - Return without throwing a SecurityException.

  • checkGuard - Return without throwing a SecurityException.

  • implies - Return true.

This behavior allows code to run as if all bundles have AllPermission.

2.3 Digitally Signed JAR Files

This section defines in detail how JAR files must be signed. This section therefore overlaps with the different JAR file specifications that are part of the different versions of Java. The reason for this duplication is that there are many aspects left as optional or not well-defined in these specifications. A reference was therefore insufficient.

Digitally signing is a security feature that verifies the following:

  • Authenticates the signer

  • Ensures that the content has not been modified after it was signed by the principal.

In an OSGi Framework, the principals that signed a JAR become associated with that JAR. This association is then used to:

  • Grant permissions to a JAR based on the authenticated principal

  • Target a set of bundles by principal for a permission to operate on or with those bundles

For example, an Operator can grant the ACME company the right to use networking on their devices. The ACME company can then use networking in every bundle they digitally sign and deploy on the Operator's device. Also, a specific bundle can be granted permission to only manage the life cycle of bundles that are signed by the ACME company.

Signing provides a powerful delegation model. It allows an Operator to grant a restricted set of permissions to a company, after which the company can create JARs that can use those permissions, without requiring any intervention of, or communication with, the Operator for each particular JAR. This delegation model is shown graphically in Figure 2.1.

Figure 2.1 Delegation model

Delegation model

Digital signing is based on public key cryptography. Public key cryptography uses a system where there are two mathematically related keys: a public and a private key. The public key is shared with the world and can be dispersed freely, usually in the form of a certificate. The private key must be kept a secret.

Messages signed with the private key can only be verified correctly with the public key. This can be used to authenticate the signer of a message (assuming the public key is trusted, this is discussed in Certificates).

The digital signing process used is based on Java JAR signing. The process of signing is repeated, restricted and augmented here to improve the interoperability of OSGi bundles.

2.3.1 JAR Structure and Manifest

A JAR can be signed by multiple signers. Each signer must store two resources in the JAR file. These resources are:

  • A signature instruction resource that has a similar format like the Manifest. It must have a .SF extension. This file provides digests for the complete manifest file.

  • A PKCS#7 resource that contains the digital signature of the signature instruction resource. See [10] Public Key Cryptography Standard #7 for information about its format.

These JAR file signing resources must be placed in the META-INF directory. For signing, the META-INF directory is special because files in there are not signed in the normal way. These signing resources must come directly after the MANIFEST.MF file, and before any other resources in a JAR stream. If this is not the case, then a Framework should not accept the signatures and must treat the bundle as unsigned. This ordering is important because it allows the receiver of the JAR file to stream the contents without buffering. All the security information is available before any resources are loaded. This model is shown in Figure 2.2.

Figure 2.2 Signer files in JAR

Signer files in JAR

The signature instruction resource contains digests of the Manifest resource, not the actual resource data itself. A digest is a one way function that computes a value from the bytes of a resource in such a way that it is very difficult to create a set of bytes that matches that digest value.

The JAR Manifest must therefore contain one or more digests of the actual resources. These digests must be placed in their name section of the manifest. The name of the digest header is constructed with its algorithm followed by -Digest. An example is the SHA-256-Digest. It is recommended that OSGi Framework implementations support the following digest algorithms.

The hash must be encoded with a Base 64 encoding. Base 64 encoding is defined in [7] RFC 1421 Privacy Enhancement for Internet Electronic Mail.

For example, a manifest could look like:

Manifest-Version: 1.0
Bundle-Name: DisplayManifest

Name: x/A.class
SHA-256-Digest: 7CCToQk6yvRusxNl0uSwrv37UY/fdz6aHou29mbswsM=

Name: x/B.class
SHA-256-Digest: C+0CG/cy13WD2sq8dRZm+dNWAHIjm4RQmUVeLLv7DVU=

Graphically this looks like Figure 2.3.

Figure 2.3 Signer files in JAR

Signer files in JAR

OSGi JARs must be signed by one or more signers that sign all resources except the ones in the META-INF directory; the default behavior of the jarsigner tool. This is a restriction with respect to standard Java JAR signing; there is no partial signing for an OSGi JAR. The OSGi specification only supports fully signed bundles. The reason for this restriction is because partially signing can break the protection of private packages. It also simplifies the security API because all code of a bundle is using the same protection domain.

Signature files in nested JAR files (For example JARs on the Bundle-ClassPath) must be ignored. These nested JAR files must share the same protection domain as their containing bundle. They must be treated as if their resources were stored directly in the outer JAR.

Each signature is based on two resources. The first file is the signature instruction file; this file must have a file name with an extension .SF. A signature file has the same syntax as the manifest, except that it starts with Signature-Version: 1.0 instead of Manifest-Version: 1.0.

The only relevant part of the signature resource is the digest of the Manifest resource. The name of the header must be the name algorithm (e.g. SHA-256) followed by -Digest-Manifest. For example:

Signature-Version: 1.0
SHA-256-Digest-Manifest: HmK7445BA7n5UYYI9xZKfSdMAPci44Jn7ZcmoyoiWoM=

The signature resource can contain name sections as well. However, these name sections should be ignored.

If there are multiple signers, then their signature instruction resources can be identical if they use the same digest algorithms. However, each signer must still have its own signature instruction file. That is, it is not allowed to share the signature resource between signers.

The indirection of the signature instruction files digests is depicted in Figure 2.4 for two signers: ACME and DAFFY.

Figure 2.4 Manifest, signature instruction files and digests in JAR

Manifest, signature instruction files and digests in JAR

2.3.2 Java JAR File Restrictions

OSGi bundles are always valid JAR files. However, there are a few restrictions that apply to bundles that do not apply to JAR files.

  • Bundles do not support partially signed bundles. The manifest must contain name sections for all resources but should not have entries for resources in the META-INF directory. Signed entries in the META-INF directory must be verified. Sub directories of META-INF must be treated like any other JAR directory.

  • The name sections in the signature files are ignored. Only the Manifest digest is used.

2.3.3 Valid Signature

A bundle can be signed with a signature by multiple signers. A signature contains a pair of a signature file, with a SF extension and a PKCS#7 resource that has the same name as the signature file but with either an RSA or DSA extension.

Such a signature is valid when:

  • The signature file has an entry for the META-INF/MANIFEST.MF resource.

  • The manifest entry must contain a SHA-256 and/or SHA-1 digest for the complete manifest.

  • All listed digests match the manifest.

  • The PKCS#7 resource is a valid signature (either signed using RSA or DSA as indicated by the extension) for the signature resource.

For a complete bundle to be validly signed it is necessary that all signatures are valid. That is, if one of the signatures is invalid, the whole bundle must be treated as unsigned.

2.3.4 Signing Algorithms

Several different available algorithms can perform digital signing. OSGi Framework implementations should support the following algorithms:

  • DSA - The Digital Signature Algorithm. This standard is defined in [8] DSA. This is a USA government standard for Digital Signature Standard. The signature resource name must have an extension of .DSA.

  • RSA - Rivest, Shamir and Adleman. A public key algorithm that is very popular. It is defined in [9] RSA. The extension of the signature resource name must be .RSA.

The signature files for RSA and DSA are stored in a PKCS#7 format. This is a format that has a structure as defined in [10] Public Key Cryptography Standard #7. The PKCS#7 standard provides access to the algorithm specific signing information as well as the certificate with the public key of the signer. The verification algorithm uses the public key to verify that:

  • The digital signature matches the signature instruction resource.

  • The signature was created with the private key associated with the certificate.

The complete signing structure is shown in Figure 2.4.

2.3.5 Certificates

A certificate is a general term for a signed document containing a name and public key information. Such a certificate can take many forms but the OSGi JAR signing is based on the X.509 certificate format. It has been around for many years and is part of the OSI group of standards. X.509 is defined in [2] X.509 Certificates.

An X.509 certificate contains the following elements:

  • Subject Name - The subject name is a unique identifier for the object being certified. In the case of a person this might include the name, nationality and e-mail address, the organization, and the department within that organization. This identifier is a Distinguished Name, which is defined in Distinguished Names.

  • Issuer Name - The Issuer name is a Distinguished Name for the principal that signed this certificate.

  • Certificate Extensions - A certificate can also include pictures, codification of fingerprints, passport number, and other extensions.

  • Public Key Information - A public key can be used with an encryption technique that requires its private counterpart to decrypt, and vice versa. The public key can be shared freely, the private key must be kept secret. The public key information specifies an algorithm identifier (such as DSA or RSA) and the subject's public key.

  • Validity - A Certificate can be valid for only a limited time.

  • Certifying Authority Signature - The Certificate Authority signs the first elements and thereby adds credibility to the certificate. The receiver of a certificate can check the signature against a set of trusted certifying authorities. If the receiver trusts that certifying authority, it can trust the statement that the certificate makes.

The structure of a certificate is depicted in Figure 2.5.

Figure 2.5 Structure of a certificate

Structure of a certificate

Certificates can be freely dispersed; they do not contain any secret information. Therefore, the PKCS#7 resource contains the signing certificate. It cannot be trusted at face value because the certificate is carried in the bundle itself. A perpetrator can easily create its own certificate with any content. The receiver can only verify that the certificate was signed by the owner of the public key (the issuer) and that it has not been tampered with. However, before the statement in the certificate can be trusted, it is necessary to authenticate the certificate itself. It is therefore necessary to establish a trust model.

One trust model, supported but not required by the OSGi specifications, is placing the signing certificate in a repository. Any certificate in this repository is treated as trusted by default. However, placing all possible certificates in this repository does not scale well. In an open model, a device would have to contain hundreds of thousands of certificates. The management of the certificates could easily become overwhelming.

The solution is to sign a certificate by another certificate, and this process can be repeated several times. This delegation process forms a chain of certificates. All certificates for this chain are carried in the PKCS#7 file: if one of those certificates can be found in the trusted repository, the other dependent ones can be trusted, on the condition that all the certificates are valid. This model scales very well because only a few certificates of trusted signers need to be maintained. This is the model used in web browsers, as depicted in Figure 2.6.

Figure 2.6 Certificate authorities fan out

Certificate authorities fan out

This specification does not specify access to the trusted repository. It is implementation specific how this repository is populated and maintained.

2.3.6 Distinguished Names

An X.509 name is a Distinguished Name (DN). A DN is a highly structured name, officially identifying a node in an hierarchical namespace. The DN concept was developed for the X.500 directory service which envisioned a world wide namespace managed by PTTs. Today, the DN is used as an identifier in a local namespace, as in a namespace designed by an Operator. For example, given a namespace that looks like Figure 2.7, the DN identifying Bugs looks like:

cn=Bug,o=ACME,c=US

Figure 2.7 Country, Company, Person based namespace.

Country, Company, Person based namespace.

The traversal of the namespace is reversed from the order in the DN, the first part specifies the least significant but most specific part. That is, the order of the attribute assertions is significant. Two DNs with the same attributes but different order are different DNs.

In the example, a node is searched in the root that has an attribute c (countryName) with a value that is US. This node is searched for a child that has an attribute o (organizationName) with a value of ACME. And the ACME node is searched for a child node with an attribute cn (commonName) that has a value "Bugs Bunny".

The tree based model is the official definition of a DN from the X.500 standards. However, in practice today, many DNs contain attributes that have no relation to a tree. For example, many DNs contain comments and copyrights in the ou (organizationalUnit) attribute.

The DN from an X.509 certificate is expressed in a binary structure defined by ASN.1 (a type language defined by ISO). However, the Distinguished Name is often used in interaction with humans. Sometimes, users of a system have to acknowledge the use of a certificate or an employee of an Operator must grant permissions based on a Distinguished Name of a customer. It is therefore paramount that the Distinguished Name has a good human readable string representation. The expressiveness of the ASN.1 type language makes this non-trivial. This specification only uses DN strings as defined in [1] RFC 2253Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names with a number of extensions that are specified by the javax.security.auth.x500.X500Principal class in CANONICAL form.

However, the complexity of the encoding/decoding is caused by the use of rarely used types and features (binary data, multi-valued RDNs, foreign alphabets, and attributes that have special matching rules). These features must be supported by a compliant implementation but should be avoided by users. In practice, these features are rarely used today.

The format of a string DN is as follows:

dn          ::= rdn ( ',' rdn ) *
rdn         ::= attribute ( '+' attribute ) *
attribute   ::= name '=' value
name        ::= readable | oid
oid         ::= number ( '.' number ) *   // See 1.3.2
readable    ::= <see attribute table>
value       ::= <escaped string>

Spaces before and after the separators are ignored, spaces inside a value are significant but multiple embedded spaces are collapsed into a single space. Wildcard asterisks ('*' \u002A) are not allowed in a value part. The following characters must be escaped with a reverse solidus ('\' \u005C):

    comma               ','     \u002C
    plus                '+'     \u002B
    double quote        '"'     \u0022
    reverse solidus     '\'     \u005C
    less then           '<'     \u003C
    greater then        '>'     \u003E
    semicolon           ';'     \u003B

Reverse solidi ('\' \u005C) must already be escaped in Java strings, requiring 2 reverse solidi in Java source code. For example:

    DN:             cn = Bugs Bunny, o = ACME++, C=US
    Canonical form: cn=bugs bunny,o=acme\+\+,c=us
    Java String:    "cn=Bugs Bunny,o=ACME\\+\\+,c=US"

The full Unicode character set is available and can be used in DNs. String objects must be normalized and put in canonical form before being compared.

    DN:             cn = Bugs Bunny, o = Ð Þ, C=US
    Canonical form: cn=bugs bunny,o=ð þ,c=us
    Java String:    "cn = Bugs Bunny, o = Ð Þ, C=US"

The names of attributes (attributes types as they are also called) are actually translated into an Object IDentifier (OID). An OID is a dotted decimal number, like 2.5.4.3 for the cn (commonName) attribute name. It is therefore not possible to use any attribute name because the implementation must know the aliasing as well as the comparison rules. Therefore only the attributes that are listed in the following table are allowed (in short or long form):

commonName              cn          2.5.4.3     ITU X.520
surName                 sn          2.5.4.4 
countryName             c           2.5.4.6
localityName            l           2.5.4.7 
stateOrProvinceName     st          2.5.4.8
organizationName        o           2.5.4.10 
organizationalUnitName  ou          2.5.4.11
title                               2.5.4.12 
givenName                           2.5.4.42 
initials                            2.5.4.43 
generationQualifier                 2.5.4.44 
dnQualifier                         2.5.4.46 

streetAddress           street                  RFC 2256
domainComponent         dc                      RFC 1274
userid                  uid                     RFC 1274/2798?
emailAddress                                    RFC 2985
serialNumber                                    RFC 2985

The following DN:

2.5.4.3=Bugs Bunny,organizationName=ACME,2.5.4.6=US

Is therefore identical to:

cn=Bugs Bunny,o=ACME,c=US

The attribute types officially define a matching rule, potentially allowing cases sensitive and case insensitive. The attributes in the previous list all match case insensitive. Therefore, an OSGi DN must not depend on case sensitivity.

The X.500 standard supports multi-valued RDNs, however, their use is not recommended. See [12] Understanding and Deploying LDAP Directory Services for the rationale of this recommendation. Multi-valued RDNs separate their constituents with a plus sign ('+' \u002B). Their order is not significant. For example:

cn=Bugs Bunny+dc=x.com+title=Manager,o=ACME,c=US

Which is the same as

dc=x.com+cn=Bugs Bunny+title=Manager, o=ACME,c=US

2.3.7 Certificate Matching

Certificates are matched by their Subject DN. Before matching, DNs, they must first be put in canonical form according to the algorithm specified in javax.security.auth.x500.X500Principal.

DNs can also be compared using wildcards. A wildcard asterisk ('*' \u002A) replaces all possible values. Due to the structure of the DN, the comparison is more complicated than string-based wildcard matching.

A wildcard can stand for a number of RDNs, or the value of a single RDN. DNs with a wildcard must be canonicalized before they are compared. This means, among other things, that spaces must be ignored, except in values.

The format of a wildcard DN match is:

CertificateMatch    ::= dn-match ( ';' dn-match) *
dn-match            ::= ( '*' | rdn-match ) 
                            ( ',' rdn-match ) * | '-' 
rdn-match           ::= name '=' value-match
value-match         ::= '*' | value-star
value-star          ::= < value, requires escaped '*' and'-' >

The most simple case is a single wildcard; it must match any DN. A wildcard can also replace the first list of RDNs of a DN. The first RDNs are the least significant. Such lists of matched RDNs can be empty.

For example, a DN with a wildcard that matches all nodes descendant from the ACME node in Figure 2.7 on page , looks like:

*, o=ACME, c=US

This wildcard DN matches the following DNs:

cn = Bugs Bunny, o = ACME, c = US
ou = Carots, cn=Daffy Duck, o=ACME, c=US
street = 9C\, Avenue St. Drézéry, o=ACME, c=US
dc=www, dc=acme, dc=com, o=ACME, c=US
o=ACME, c=US

The following DNs must not match:

street = 9C\, Avenue St. Drézéry, o=ACME,c=FR
dc=www, dc=acme, dc=com, c=US

If a wildcard is used for a value of an RDN, the value must be exactly *. The wildcard must match any value, and no substring matching must be done. For example:

cn=*,o=ACME,c=*

This DN with wildcard must match the following DNs:

cn=Bugs Bunny,o=ACME,c=US
cn = Daffy Duck , o = ACME , c = US
cn=Road Runner, o=ACME, c=NL

But not:

o=ACME, c=NL
dc=acme.com, cn=Bugs Bunny, o=ACME, c=US

Both forms of wildcard usage can be combined in a single matching DN. For example, to match any DN that is from the ACME company worldwide, use:

*, o=ACME, c=*

Matching of a DN takes place in the context of a certificate. This certificate is part of a certificate chain, see Certificates. Each certificate has a Subject DN and an Issuer DN. The Issuer DN is the Subject DN used to sign the first certificate of the chain. DN matching can therefore be extended to match the signer. The semicolon (';' \u003B) must be used to separate DNs in a chain.

The following example matches a certificate signed by Tweety Inc. in the US.

* ; ou=S & V, o=Tweety Inc., c=US

The wildcard matches zero or one certificates, however, sometimes it is necessary to match a longer chain. The minus sign ('-' \u002D) represents zero or more certificates, whereas the asterisk only represents a single certificate. For example, to match a certificate where the Tweety Inc. is in the certificate chain, use the following expression:

- ; *, o=Tweety Inc., c=US

The previous example matched if the Tweety Inc. certificate was trusted, or was signed by a trusted certificate. Certain certificates are trusted because they are known by the Framework, how they are known is implementation-defined.

2.4 Permissions

The OSGi Framework uses Java permissions for securing bundles. Each bundle is associated with a set of permissions. During runtime, the permissions are queried when a permission is requested through the Security Manager. If a Framework uses postponed conditions, then it must install its own security manager, otherwise it can use any Security Manager.

The management of the bundle's permissions is handled through Conditional Permission Admin, Permission Admin, or another security agent.

2.4.1 Implied Permissions

Implied permissions are permissions that the framework grants a bundle without any specific action. These permissions are necessary for normal operation. For example, each bundle gets permissions to read, write, and delete the bundle persistent storage area. The standard list of implied permissions is as follows:

  • File Permission for the bundle persistent storage area, for the READ, WRITE, and DELETE actions.

  • Property Permission with the READ action for org.osgi.framework.*.

  • Admin Permission with the RESOURCE, METADATA, CLASS, and CONTEXT actions for the bundle itself.

  • Capability Permission REQUIRE for the osgi.ee namespace.

  • Capability Permission REQUIRE for the osgi.native namespace.

  • Package Permission IMPORT for java.*.

  • Service Permission GET for org.osgi.service.condition.Condition

2.4.2 Filter Based Permissions

OSGi supports a number of permissions that are granted when the target of the permissions is related to a bundle. For example, Admin Permission can grant a bundle the permission to manage other bundles. This is expressed by using a filter expression for the name of the permission. When the permission is checked, the filter is evaluated with specific permission attributes as well as attributes that describe the bundle's identity. For example, a bundle can get permission to get all services registered by bundles coming from a specific location:

ServicePermission("(location=https://www.acme.com/*)",GET )

This provides a very powerful model because it allows operators to let a group of bundles closely collaborate without requiring ad hoc namespaces for services, packages, and bundles. Using the signer or location as the target for a permission, will allow the maintenance of the permission management to be significantly reduced. It is not necessary to configure for individual bundles: the signer or location is effectively used as a grouping mechanism.

The filter can contain the following keys:

  • id - The bundle ID of a bundle. For example:

    (id=256)
  • location - The location of a bundle. Filter wildcards for Strings are supported, allowing the value to specify a set of bundles. For example:

    (location=https://www.acme.com/download/*)
  • signer - A Distinguished Name chain. See Certificate Matching for more information how Distinguished Names are matched. Wildcards in a DN are not matched according to the filter string rules, but according to the rules defined for a DN chain. The wildcard asterisk ('*' \u002A) must be escaped with a reverse solidus ('\' \u005C) to avoid being interpreted as a filter wildcard. For example:

    (signer=\*,o=ACME,c=NL)
  • name - The symbolic name of a bundle. Filter wildcards for Strings are supported allowing the value to specify a set of bundles. A single symbolic name may also map to a set of bundles. For example:

    (name=com.acme.*)

The name parameter of the permission can also be a single wildcard asterisk ('*' \u002A). In that case all bundles must match.

2.4.2.1 Multiple Signers

A bundle can be signed by multiple signers, in that case the signer will match against any of the signers' DN. Using multiple signers is both a feature as well as it is a possible threat. From a management perspective it is beneficial to be able to use signatures to handle the grouping. However, it could also be used to maliciously manage a trusted bundle.

For example a trusted bundle signed by T, could later have a signature added by an untrusted party U. This will grant the bundle the permissions of both T and U, which ordinarily is a desirable feature. However, If the permissions associated with signer U also allow the management of bundles signed by U, then U could unexpectedly gain the permission to manage this trusted bundle. For example, it could now start and stop this trusted bundle. This unexpected effect of becoming eligible to be managed should be carefully considered when multiple signers are used. The deny policies in Conditional Permission Admin can be used to prevent this case from causing harm.

2.5 References

[1]RFC 2253Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Nameshttps://www.ietf.org/rfc/rfc2253.txt

[7]RFC 1421 Privacy Enhancement for Internet Electronic Mailhttps://www.ietf.org/rfc/rfc1421.txt

[10]Public Key Cryptography Standard #7https://www.ietf.org/rfc/rfc2315.txt

[11]Unicode Normalization UAX # 15https://www.unicode.org/reports/tr15/

[12]Understanding and Deploying LDAP Directory ServicesISBN 1-57870-070-1