NSS API Structure
Libraries
NSS compiles into the libraries described below. The Layer indicates the main layer in which the library operates. The Directory is the location of the library code in the NSS source tree. The Public Headers is a list of header files that contain types, and functions, that are publicly available to higer-level APIs.
Library |
Description |
Layer |
Directory |
Public Headers |
certdb |
Provides all certificate handling functions and types. The certdb library manipulates the certificate database (add, create, delete certificates and CRLs). It also provides general c ertificate-handling routines (create a certificate, verify, add/check certificate extensions). |
Low Cert |
lib/certdb |
cdbhdl.h, certdb.h, cert.h, certt.h |
certhi |
Provides high-level certificate-related functions, that do not access the certificate database, nor individual certificate data directly. Currently, OCSP checking settings are exported through certhi. |
High Cert |
lib/certhigh |
ocsp.h, ocspt.h |
crmf |
Provides functions, and data types, to handle Certificate Management Message Format (CMMF) and Certificate Request Message Format (CRMF, see RFC 2511) data. CMMF no longer exists as a proposed standard; CMMF functions have been incorporated into the proposal for Certificate Management Protocols (CMP). |
Same Level as SSL |
lib/crmf |
cmmf.h, crmf.h, crmft.h, cmmft.h, crmffut.h |
cryptohi |
Provides high-level cryptographic support operations: such as signing, verifying signatures, key generation, key manipulation, hashing; and data types. This code is above the PKCS #11 layer. |
Sign/Verify |
lib/cryptohi |
cryptohi.h, cryptoht.h, hasht.h, keyhi.h, keythi.h, key.h, keyt.h, sechash.h |
fort |
Provides a PKCS #11 interface, to Fortezza crypto services. Fortezza is a set of security algorithms, used by the U.S. government. There is also a SWFT library that provides a software-only implementation of a PKCS #11 Fortezza token. |
PKCS #11 |
lib/fortcrypt |
cryptint.h, fmutex.h, fortsock.h, fpkcs11.h, fpkcs11f.h, fpkcs11t.h, fpkmem.h, fpkstrs.h, genci.h, maci.h |
freebl |
Provides the API to actual cryptographic operations. The freebl is a wrapper API. You must supply a library that implements the cryptographic operations, such as BSAFE from RSA Security. This is also known as the “bottom layer” API, or BLAPI. |
Within PKCS #11, wraps Crypto |
lib/freebl |
blapi.h, blapit.h |
jar |
Provides support for reading and writing data in Java Archive (jar) format, including zlib compression. |
Port |
lib/jar |
jar-ds.h, jar.h, jarfile.h |
nss |
Provides high-level initialiazation and shutdown of security services. Specifically, this library provides NSS_Init() for establishing default certificate, key, module databases, and initializing a default random number generator. NSS_Shutdown() closes these databases, to prevent further access by an application. |
Above High Cert, High Key |
lib/nss |
nss.h |
pk11wrap |
Provides access to PKCS #11 modules, through a unified interface. The pkcs11wrap library provides functions for selecting/finding PKCS #11 modules and slots. It also provides functions that invoke operations in selected modules and slots, such as key selection and generation, signing, encryption and decryption, etc. |
Crypto Wrapper |
lib/pk11wrap |
pk11func.h, secmod.h, secmodt.h |
pkcs12 |
Provides functions and types for encoding and decoding PKCS #12 data. PKCS #12 can be used to encode keys, and certificates, for export or import into other applications. |
PKCS #12 |
lib/pkcs12 |
pkcs12t.h, pkcs12.h, p12plcy.h, p12.h, p12t.h |
pkcs7 |
Provides functions and types for encoding and decoding encrypted data in PKCS #7 format. For example, PKCS #7 is used to encrypt certificate data to exchange between applications, or to encrypt S/MIME message data. |
PKCS #7 |
lib/pkcs7 |
secmime.h, secpkcs7.h, pkcs7t.h |
softoken |
Provides a software implementation of a PKCS #11 module. |
PKCS #11: implementation |
lib/softoken |
keydbt.h, keylow.h, keytboth.h, keytlow.h, secpkcs5.h, pkcs11.h, pkcs11f.h, pkcs11p.h, pkcs11t.h, pkcs11u.h |
ssl |
Provides an implementation of the SSL protocol using NSS and NSPR. |
SSL |
lib/ssl |
ssl.h, sslerr.h, sslproto.h, preenc.h |
secutil |
Provides utility functions and data types used by other libraries. The library supports base-64 encoding/decoding, reader-writer locks, the SECItem data type, DER encoding/decoding, error types and numbers, OID handling, and secure random number generation. |
Utility for any Layer |
lib/util |
base64.h, ciferfam.h, nssb64.h, nssb64t.h, nsslocks.h, nssrwlk.h, nssrwlkt.h, portreg.h, pqgutil.h, secasn1.h, secasn1t.h, seccomon.h, secder.h, secdert.h, secdig.h, secdigt.h, secitem.h, secoid.h, secoidt.h, secport.h, secrng.h, secrngt.h, secerr.h, watcomfx.h |
Naming Conventions
This section describes the rules that (ideally) should be followed for naming and identifying new files, functions, and data types.
Header Files
Data Types |
Function Prototypes |
|
Public |
nss____t.h |
nss____.h |
Friend (only if required) |
nss____tf.h |
nss____f.h |
NSS-private |
____t.h |
____.h |
Module-private |
____tm.h |
____m.h |
The files on the right include the files to their left; the files in a row include the files directly above them. Header files always include what they need; the files are protected against double inclusion (and even double opening by the compiler).
Note
Note: It’s not necessary all eight files exist. Further, this is a simple ideal, and often reality is more complex.
We would like to keep names to 8.3, even if we no longer support win16. This usually gives us four characters to identify a module of NSS.
In short:
Header files for consumption outside NSS start with “nss.”
Header files with types have a trailing “t”, header files with prototypes don’t. “extern” declarations of data also go in the prototypes files.
“Friend” headers are for things that we really wish weren’t used by non-NSS code, but which are. Those files have a trailing “f,” and their use should be deprecated.
“Module” headers are for things used only within a specific subset of NSS; things which would have been “static” if we had combined separate C source files together. These header files have a trailing “m.”
Functions and Types
There are a number of ways of doing things in our API, as well as naming decisions for functions that can affect the usefulness of our library. If our library is self-consistent with how we accomplish these tasks, it makes it easier for the developer to learn how to use our functions. This section of the document should grow as we develop our API.
First some general rules. These rules are derived from existing coding practices inside the security library, since consistency is more important than debates about what might look nice.
Public functions should have the form LAYER_Body(), where LAYER is an all caps prefix for what layer the function lives in, and Body is concatenated English words, where the beginning letter of each word is capitalized (also known as CamelCase). For Example: LAYER_CapitalizedEnglishWords() or CERT_DestroyCertificate().
Data types and typdefs should have the Form LAYERBody, with the same definitions for LAYER as public functions, and Body in camel case English words. For example: LAYERCapitalizedEnglishWords or SECKEYPrivateKey.
Structures should have the same name as their typedefs, with the string Str added to the end. For example LAYERCapitalizedEnglishWordsStr or SECKEYPrivateKeyStr.
Private functions should have the form layer_Body(), where layer is the all lower case prefix for what layer the function lives in, and Body is camel case English words. Private functions include functions that may be “public” in a C sense, but are not exported out of the layer. For example: layer_CapitalizedEnglishWords() or pk11_GenerateKeyID().
Public macros should have the form LAYER_BODY(), where LAYER is an all caps prefix for what layer the macro lives in, and BODY is English words, all in upper case, separated by underscores. For example: LAYER_UPPER_CASE_ENGLISH_WORDS() or DER_CONVERT_BIT_STRING().
Structure members for exposed data structures should have the form capitalizedEnglishWords (the first letter uncapitalized). For example: PK11RSAGenParamsStr.keySizeInBits
For members of enums, our current API has no standard (typedefs for enums should follow the Data types standard). There seem to be three reasonable options:
Enum members have the same standard as exposed data structure members.
Enum members have the same standard as data types.
Enum members have the same standard as public macros (minus the ‘()’ of course).
Options 2 and 3 are the more preferred options. Option 1, currently the most common used for enums, actually creates namespace pollution.
Callback functions, and functions used in function tables, should have a typedef used to define the complete signature of the given function. Function typedefs should have the following format: LAYERBody(), with the same definitions for LAYER as public functions, and Body is camel case English words. For example: LAYERCapitalizedEnglishWords or SECKEYPrivateKey.
Opaque Data Structures
There are many data structures in the security library whose definition is effectively private, to the portion of the security library that defines and operates on those data structures. External code does not have access to these definitions. The goal here is to increase the opaqueness of these structures. This will allow us to modify the size, definition, and format of these data structures in future releases, without interfering with the operation of existing applications that use the security library.
The first task is to ensure the data structure definition lives in a private header file, while its declaration lives in the public. The current standard in the security library is to typedef the data structure name, the easiest way to accomplish this would be to add the typedef to the public header file.
For example, for the structure SECMyOpaqueData you would add:
typedef struct SECMyOpaqueDataStr SECMyOpaqueData;
and add the actual structure definition to the private header file. In this same example:
struct SECMyOpaqueDataStr {
unsigned long myPrivateData1;
unsigned long myPrivateData2;
char *myName;
};
the second task is to determine if individual data fields, within the data structure, are part of the API.