summaryrefslogtreecommitdiffstats
path: root/security/nss/doc/rst/legacy/nss_tech_notes
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /security/nss/doc/rst/legacy/nss_tech_notes
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/nss/doc/rst/legacy/nss_tech_notes')
-rw-r--r--security/nss/doc/rst/legacy/nss_tech_notes/index.rst23
-rw-r--r--security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note1/index.rst196
-rw-r--r--security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note2/index.rst167
-rw-r--r--security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note3/index.rst234
-rw-r--r--security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note4/index.rst221
-rw-r--r--security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note5/index.rst659
-rw-r--r--security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note6/index.rst104
-rw-r--r--security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note7/index.rst189
-rw-r--r--security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note8/index.rst130
9 files changed, 1923 insertions, 0 deletions
diff --git a/security/nss/doc/rst/legacy/nss_tech_notes/index.rst b/security/nss/doc/rst/legacy/nss_tech_notes/index.rst
new file mode 100644
index 0000000000..ddd92f87cd
--- /dev/null
+++ b/security/nss/doc/rst/legacy/nss_tech_notes/index.rst
@@ -0,0 +1,23 @@
+.. _mozilla_projects_nss_nss_tech_notes:
+
+NSS Tech Notes
+==============
+
+.. container::
+
+ Newsgroup: `mozilla.dev.tech.crypto <news://news.mozilla.org/mozilla.dev.tech.crypto>`__
+
+ NSS technical notes provide latest information about new NSS features and supplementary
+ documentation for advanced topics in programming with NSS.
+
+ #. TN1: `How to use the NSS ASN.1 and QuickDER decoders <nss_tech_notes/nss_tech_note1>`__.
+ #. TN2: `Using the PKCS #11 Module Logger <nss_tech_notes/nss_tech_note2>`__.
+ #. TN3: `All About Certificate Extensions <nss_tech_notes/nss_tech_note3>`__.
+ #. TN4: `Pulling certificate extension information out of SSL
+ certificates <nss_tech_notes/nss_tech_note4>`__.
+ #. TN5: `Using NSS to perform miscellaneous cryptographic
+ operations <nss_tech_notes/nss_tech_note5>`__.
+ #. TN6: `NSS .chk Files for the FIPS Mode <nss_tech_notes/nss_tech_note6>`__.
+ #. TN7: `RSA Signing and Encryption with NSS <nss_tech_notes/nss_tech_note7>`__.
+ #. TN8: `Background Information on libSSL's Cache Functions and
+ SIDs <nss_tech_notes/nss_tech_note8>`__. \ No newline at end of file
diff --git a/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note1/index.rst b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note1/index.rst
new file mode 100644
index 0000000000..3b8313fd3a
--- /dev/null
+++ b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note1/index.rst
@@ -0,0 +1,196 @@
+.. _mozilla_projects_nss_nss_tech_notes_nss_tech_note1:
+
+nss tech note1
+==============
+
+.. _how_to_use_the_nss_asn.1_and_quickder_decoders:
+
+`How to use the NSS ASN.1 and QuickDER decoders <#how_to_use_the_nss_asn.1_and_quickder_decoders>`__
+----------------------------------------------------------------------------------------------------
+
+.. container::
+
+.. _nss_technical_note_1:
+
+`NSS Technical Note: 1 <#nss_technical_note_1>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ NSS 3.6 contains several decoders for ASN.1 and DER.Two of them are extensively used and are part
+ of the public NSS API :
+
+ #. The "classic" ASN.1 decoder, written by Lisa Repka . This was written to be a generic decoder,
+ that includes both DER (Distinguished Encoding Rules) and BER (Basic Encoding Rules).† It
+ handles both streaming and non-streaming input.
+ #. The "QuickDER" decoder, written by Julien Pierre for NSS 3.6 . This decoder was written when
+ performance issues were discovered with the classic decoder. It can only decode DER .† It does
+ not handle streaming input, and requires that all input be present before beginning to decode.
+
+ Despite their differences, the two decoders have a lot in common. QuickDER was written to be as
+ compatible as possible with the classic decoder, in order to ease migration to it in areas of
+ critical performance bottlenecks. For this reason, I will first describe all the common
+ functionality of the two decoders, before outlining their differences.
+ The main non-streaming APIs for these two decoders have an identical prototype :
+
+ - SECStatus SEC_ASN1DecodeItem(PRArenaPool \*pool, void \*dest, const SEC_ASN1Template \*t,
+ SECItem \*item);
+ - SECStatus SEC_QuickDERDecodeItem(PRArenaPool\* arena, void\* dest, const SEC_ASN1Template\*
+ templateEntry, SECItem\* src);
+
+ Here is a description of the arguments :
+
+ - *SECItem\* src*\ † is a structure containing a pointer to the binary data to be decoded, as
+ well as its size.
+ - *const SEC_ASN1Template\* templateEntry* is a pointer to one or more `decoder
+ templates <#templates>`__. The number of required templates is determined by the type of the
+ first template.When multiple templates are required, the pointer must point to a
+ NULL-terminated array of templates. The syntax of these templates is identical for both
+ decoders, except where noted. A "NULL Template" is a template that is all zeros, having a zero
+ kind.† The term "NULL-terminated array", as used throughout this document, means an array of
+ templates, the last of which is a NULL template.
+ - *void\* dest* is a pointer to the target area. This is where the decoder stores its output.
+ The type is undefined as it is completely dependent on the content of the decoder templates.†
+ This typically points to a struct that is described (or partially described) by the templates.
+ - *PRArenaPool\* arena* is a pointer to an NSPR arena pool. This is the arena pool from which
+ the decoder will allocate memory as needed.
+
+ Decoder templates :
+ The SEC_ASN1Template structure tells the decoder what to do with the input data. This structure
+ contains four fields :
+
+ - *kind* . This 32-bit field tells the decoder what to do with a particular component within the
+ input data. It is made of two parts : the lower byte, which can contain `ASN.1
+ tags <#asn.1_tags>`__, and the upper 3 bytes, which can contain `decoder
+ modifiers <#decoder_modifiers>`__. If only an ASN.1 tag is specified without a modifier, then
+ the decoder will enforce the presence of a component of that type, and fail if it does not
+ match. If kind is an ASN.1 SEQUENCE tag (SEC_ASN1_SEQUENCE), then you must specify additional
+ templates in a NULL-terminated array to define the content of the of the ASN.1 SEQUENCE. If
+ kind is the SEC_ASN1_CHOICE modifier, you must also specify additional templates in a NULL
+ terminated array to list the various possible types that this component can have. In all other
+ cases, only the first template structure passed to the decoder will be considered, even if
+ additonal templates are passed in an array. When only one template is needed, you do not need
+ a NULL template to terminate the array.
+ - *offset*\ † . This field does not apply to all template types. It is only needed if the
+ template instructs the decoder to save some data, such as for primitive component types, or
+ for some modifiers where noted.When needed, it tells the decoder where in the target data to
+ save the current component. It is normally relative to the dest argument passed to the
+ decoder. If templates are nested, the offset applies to the location of the current component
+ within the target component, typically the decoded SEQUENCE.
+ - *sub*\ † . This field does not apply to all template types. If kind contains the
+ SEC_ASN1_INLINE or SEC_ASN1_POINTER modifiers, then it must point to the required subtemplate.
+ If kind contains the SEC_ASN1_XTRN or SEC_ASN1_DYNAMIC modifiers, this is a pointer to a
+ callback function that will dynamically return the required subtemplate.
+ - *size*\ † . This field does not apply to all template types. It is only required for
+ dynamically allocating memory for the structure if the template is being included from an
+ ASN.1 SEQUENCE or SEQUENCE OF, or if dynamic allocation was requested from the parent template
+ using the SEC_ASN1_POINTER modifier
+
+ Here is a description of the various tags and modifiers that apply to the kind field.
+ *ASN.1 tags*
+
+ | ASN.1 tags are specified in the lower byte of the kind field of the template, as noted above.
+ | The following is not an attempt to explain ASN.1 tags or their purposes. Rather, the goal here
+ is to explain what type of tags the decoder supports and which macros should be used when
+ defining tags in decoder templates. It should be noted that we only support an older
+ specification of ASN.1; multibyte tags are not currently supported.
+
+ The 8-bit ASN.1 tags that we support are made of three parts :
+
+ #. The ASN.1 component class type. It is specified in the upper 2 tag bits (number 6 and 7).
+ There are four classes of ASN.1 tags : universal, application-specific, context-specific, and
+ private. You can specify the class of the tag using the macros SEC_ASN1_UNIVERSAL,
+ SEC_ASN1_APPLICATION, SEC_ASN1_CONTEXT_SPECIFIC and SEC_ASN1_PRIVATE. Universal is the default
+ tag class and does not have to be specified, as the value of the class type is zero.
+
+ #. The method type : whether the component type is constructed or primitive. This information is
+ stored in the next lowest tag bit (number 5). You can use the macro SEC_ASN1_CONSTRUCTED for a
+ constructed component type. A SEC_ASN1_PRIMITIVE macro is also provided, but does not need to
+ be included as it is zero.
+
+ #. | The tag number. It is stored in the lower 5 tag bits (number 0 through 4). The ASN.1
+ standard only defines tag numbers in the universal class. If you are using a tag of a
+ different classes, you can define your own tag number macros or specify the tag value within
+ the template definition. The following macros are provided for tag numbers within the
+ universal class :
+ | SEC_ASN1_BOOLEAN, SEC_ASN1_INTEGER, SEC_ASN1_BIT_STRING, SEC_ASN1_OCTET_STRING,
+ SEC_ASN1_NULL, SEC_ASN1_OBJECT_ID, SEC_ASN1_OBJECT_DESCRIPTOR,† SEC_ASN1_REAL,
+ SEC_ASN1_ENUMERATED, SEC_ASN1_EMBEDDED_PDV, SEC_ASN1_UTF8_STRING, SEC_ASN1_SEQUENCE,
+ SEC_ASN1_SET, SEC_ASN1_NUMERIC_STRING, SEC_ASN1_PRINTABLE_STRING, SEC_ASN1_T61_STRING,
+ SEC_ASN1_TELETEX_STRING, SEC_ASN1_T61_STRING, SEC_ASN1_VIDEOTEX_STRING, SEC_ASN1_IA5_STRING,
+ SEC_ASN1_UTC_TIME, SEC_ASN1_GENERALIZED_TIME, SEC_ASN1_GRAPHIC_STRING,
+ SEC_ASN1_VISIBLE_STRING, SEC_ASN1_GENERAL_STRING, SEC_ASN1_UNIVERSAL_STRING,
+ SEC_ASN1_BMP_STRING
+
+ Note that for SEC_ASN1_SET and SEC_ASN1_SEQUENCE types, you must also include the method type
+ macro SEC_ASN1_CONSTRUCTED to construct a fully valid tag, as defined by the ASN.1 standard .
+
+ *Decoder modifiers :*
+ These modifiers are also specified in the kind field of the template structure. All the values
+ are in the 9 - 31 bit range.
+
+ - *SEC_ASN1_OPTIONAL*: tells the decoder that this component is optional. If the component in
+ the input data does not match this template, the decoder will continue processing the input
+ data using the next available template.
+ - *SEC_ASN1_EXPLICIT*: tells the decoder that explicit tagging is being used. This is always a
+ constructed type. It requires a subtemplate defining the types of the data within.
+ - *SEC_ASN1_ANY*: allows the decoder to match this template with any component type, regardless
+ of the tag in the input data. If used in conjunction with SEC_ASN1_OPTIONAL as part of a
+ sequence, this must be the last template in the template array.
+ - *SEC_ASN1_INLINE*: recurse into the specified subtemplate to continue processing. This is
+ typically used for SEC_ASN1_SEQUENCE or SEC_ASN1_CHOICE definitions, which always need to be
+ the first template in a template array of their own.
+ - *SEC_ASN1_POINTER*: similar to SEC_ASN1_INLINE, except that the memory in the target will be
+ allocated dynamically and a pointer to the dynamically allocated memory will be stored in the
+ *dest* struct at the *offset*. This requires that the subtemplate contains a non-zero size
+ field.
+ - *SEC_ASN1_GROUP*: can only be used in conjunction with a SEC_ASN1_SET or SEC_ASN1_SEQUENCE. It
+ tells the decoder that the component is an ASN.1 SET OF or SEQUENCE OF respectively. You can
+ also use the macros SEC_ASN1_SET_OF and SEC_ASN1_SEQUENCE_OF which define both the tag number
+ and this modifier (but still need the method type, this may be a bug).
+ - *SEC_ASN1_DYNAMIC* or *SEC_ASN1_XTRN* : specifies that the component format is defined in a
+ dynamic subtemplate. There is no difference between the two macros. The sub field of the
+ template points to a callback function of type SEC_ASN1TemplateChooser that returns the
+ subtemplate depending on the component data.
+ - *SEC_ASN1_SKIP*: specifies that the decoder should skip decoding of the component.
+ SEC_ASN1DecodeItem can only skip required components and will assert if you try to skip an
+ OPTIONAL component. SEC_QuickDERDecodeItem supports skipping the decoding of OPTIONAL
+ components if you define the tag of the component in the template
+ - *SEC_ASN1_INNER*: recurse into the component and saves its content, without the surrounding
+ ASN.1 tag and length
+ - *SEC_ASN1_SAVE*: saves the component data, but does not proceed to the next component if
+ within a SEQUENCE template array. This means the next template will reprocess the same
+ component.
+ - *SEC_ASN1_SKIP_REST*: abort the decoding. This is used in a template array within a SEQUENCE,
+ if you don't care about the fields at the end of it. SEC_ASN1DecodeItem only supports this
+ modifier in the top-level template. SEC_QuickDERDecodeItem allows it at any nested sublevel.
+ - *SEC_ASN1_CHOICE*: allows decoding of components that are of variable type. This must be the
+ first template in a NULL-terminated array. The offset parameter specifies where to store the
+ type identifier in the target data . Subsequent templates specify a custom identifier for each
+ possible component type in the size parameter .
+ - *SEC_ASN1_DEBUG_BREAK*: makes the decoder assert when processing the template. This option is
+ only supported with SEC_QuickDERDecodeItem . It is useful to debug your templates or when
+ writing new templates if they don't work.
+
+ |
+ | *Differences between SEC_ASN1DecodeItem and SEC_QuickDERDecodeItem*
+
+ #. The arena argument is required to be non-NULL for SEC_QuickDERDecodeItem . With
+ SEC_ASN1DecodeItem, it can be NULL, and if so, the decoder will allocate from the heap using
+ PR_Malloc . However, this usage is strongly discouraged and we recommend that you always use
+ an arena pool even with SEC_ASN1DecodeItem. See `bug
+ 175163 <http://bugzilla.mozilla.org/show_bug.cgi?id=175163>`__ for more information about the
+ reason for this recommendation.
+ #. SEC_ASN1DecodeItem will make a copy of the input data into the decoded target as needed, while
+ SEC_QuickDERDecodeItem will generate output with pointers into the input. This means that if
+ you use SEC_QuickDERDecodeItem, you must always be careful not to free the input as long as
+ you intend to use the decoded structure. Ideally, you should allocate the input data out of
+ the same arena that you are passing to the decoder. This will allow you to free both the input
+ data and the decoded data at once when freeing the arena.
+ #. SEC_ASN1DecodeItem can decode both BER and DER data, while SEC_QuickDERDecodeItem can only
+ decode DER data.
+ #. SEC_QuickDERDecodeItem does not support streaming data. This feature will most likely never be
+ added, as this decoder gets most of its extra speed from not making a copy of the input data,
+ which would be required when streaming.
+ #. SEC_QuickDERDecodeItem supports SEC_ASN1_OPTIONAL together with SEC_ASN1_SKIP
+ #. SEC_ASN1_DEBUG_BREAK is not supported by SEC_ASN1DecodeItem \ No newline at end of file
diff --git a/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note2/index.rst b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note2/index.rst
new file mode 100644
index 0000000000..efc80ff3a4
--- /dev/null
+++ b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note2/index.rst
@@ -0,0 +1,167 @@
+.. _mozilla_projects_nss_nss_tech_notes_nss_tech_note2:
+
+nss tech note2
+==============
+
+.. container::
+
+ .. rubric:: Using the PKCS #11 Module Logger
+ :name: Using_the_PKCS_11_Module_Logger
+
+.. _nss_technical_note_2:
+
+`NSS Technical Note: 2 <#nss_technical_note_2>`__
+-------------------------------------------------
+
+.. container::
+
+ - `Modes of Operation <#modes>`__
+ - `Extracting Output from Log files <#extracting>`__
+
+ The logger displays all activity between NSS and a specified PKCS #11 module. It works by
+ inserting a special set of entry points between NSS and the module.
+
+ To enable the module logger, you must set the environment variable NSS_DEBUG_PKCS11_MODULE to the
+ name of the target module. For example, to log the softoken, use:
+
+ .. code::
+
+ NSS_DEBUG_PKCS11_MODULE="NSS Internal PKCS #11 Module"
+
+ Note: In the Command Prompt on Windows, do not quote the name of the target module, otherwise the
+ quotes are considered part of the name. For example, to log the softoken on Windows, use:
+
+ .. code::
+
+ set NSS_DEBUG_PKCS11_MODULE=NSS Internal PKCS #11 Module
+
+ The logger is available by default in debug builds. For optimized builds, NSS must be built with
+ the variable DEBUG_PKCS11 set.
+
+.. _modes_of_operation:
+
+`Modes of Operation <#modes_of_operation>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ The logger has several modes of operation:
+
+ **1. Only display the sequence of PKCS #11 calls.** To enable this mode, set:
+
+ .. code::
+
+ NSPR_LOG_MODULES=nss_mod_log:1
+ NSPR_LOG_FILE=<logfile>
+
+ The output format is:
+
+ .. code::
+
+ OSThreadID[NSPRThreadID]: C_XXX
+ OSThreadID[NSPRThreadID]: rv = 0xYYYYYYYY
+
+ For example,
+
+ .. code::
+
+ 1024[805ef10]: C_Initialize
+ 1024[805ef10]: rv = 0x0
+ 1024[805ef10]: C_GetInfo
+ 1024[805ef10]: rv = 0x0
+ 1024[805ef10]: C_GetSlotList
+ 1024[805ef10]: rv = 0x0
+
+ **2. Display the sequence of PKCS #11 calls, and the parameters given to them.** To enable this
+ mode, set:
+
+ .. code::
+
+ NSPR_LOG_MODULES=nss_mod_log:3
+ NSPR_LOG_FILE=<logfile>
+
+ The output format is:
+
+ .. code::
+
+ OSThreadID[NSPRThreadID]: C_XXX
+ OSThreadID[NSPRThreadID]: arg1 = 0xAAAAAAAA
+ ...
+ OSThreadID[NSPRThreadID]: argN = 0xAAAAAAAA
+ OSThreadID[NSPRThreadID]: rv = 0xYYYYYYYY
+
+ For example,
+
+ .. code::
+
+ 1024[805ef10]: C_Initialize
+ 1024[805ef10]: pInitArgs = 0x4010c938
+ 1024[805ef10]: rv = 0x0
+ 1024[805ef10]: C_GetInfo
+ 1024[805ef10]: pInfo = 0xbffff340
+ 1024[805ef10]: rv = 0x0
+ 1024[805ef10]: C_GetSlotList
+ 1024[805ef10]: tokenPresent = 0x0
+ 1024[805ef10]: pSlotList = 0x0
+ 1024[805ef10]: pulCount = 0xbffff33c
+ 1024[805ef10]: *pulCount = 0x2
+ 1024[805ef10]: rv = 0x0
+
+ Note that when a PKCS #11 function takes a pointer argument for which it will set a value
+ (C_GetSlotList above), this mode will display the value upon return.
+
+ **3. Display verbose information, including template values, array values, etc.** To enable this
+ mode, set:
+
+ .. code::
+
+ NSPR_LOG_MODULES=nss_mod_log:4
+ NSPR_LOG_FILE=<logfile>
+
+ The output format is the same as above, but with more information. For example,
+
+ .. code::
+
+ 1024[805ef10]: C_FindObjectsInit
+ 1024[805ef10]: hSession = 0x1000001
+ 1024[805ef10]: pTemplate = 0xbffff410
+ 1024[805ef10]: ulCount = 3
+ 1024[805ef10]: CKA_LABEL = localhost.nyc.rr.com [20]
+ 1024[805ef10]: CKA_TOKEN = CK_TRUE [1]
+ 1024[805ef10]: CKA_CLASS = CKO_CERTIFICATE [4]
+ 1024[805ef10]: rv = 0x0
+ 1024[805ef10]: C_FindObjects
+ 1024[805ef10]: hSession = 0x1000001
+ 1024[805ef10]: phObject = 0x806d810
+ 1024[805ef10]: ulMaxObjectCount = 16
+ 1024[805ef10]: pulObjectCount = 0xbffff38c
+ 1024[805ef10]: *pulObjectCount = 0x1
+ 1024[805ef10]: phObject[0] = 0xf6457d04
+ 1024[805ef10]: rv = 0x0
+ 1024[805ef10]: C_FindObjectsFinal
+ 1024[805ef10]: hSession = 0x1000001
+ 1024[805ef10]: rv = 0x0
+ 1024[805ef10]: C_GetAttributeValue
+ 1024[805ef10]: hSession = 0x1000001
+ 1024[805ef10]: hObject = 0xf6457d04
+ 1024[805ef10]: pTemplate = 0xbffff2d0
+ 1024[805ef10]: ulCount = 2
+ 1024[805ef10]: CKA_TOKEN = 0 [1]
+ 1024[805ef10]: CKA_LABEL = 0 [20]
+ 1024[805ef10]: rv = 0x0
+ 1024[805ef10]: C_GetAttributeValue
+ 1024[805ef10]: hSession = 0x1000001
+ 1024[805ef10]: hObject = 0xf6457d04
+ 1024[805ef10]: pTemplate = 0xbffff2d0
+ 1024[805ef10]: ulCount = 2
+ 1024[805ef10]: CKA_TOKEN = CK_TRUE [1]
+ 1024[805ef10]: CKA_LABEL = localhost.nyc.rr.com [20]
+ 1024[805ef10]: rv = 0x0
+
+ **4. Collect performance data.** This mode is most useful in optimized builds. The number of
+ calls to each PKCS #11 function will be counted, and the time spent in each function as well. A
+ summary of performance data is dumped during NSS shutdown.
+
+ No additional environment variables are required for this mode. If the environment variable
+ NSS_OUTPUT_FILE is set, its value will be used as the path name of the file to which the final
+ output will be written. Otherwise, the output will be written to stdout. \ No newline at end of file
diff --git a/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note3/index.rst b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note3/index.rst
new file mode 100644
index 0000000000..2d72c870cc
--- /dev/null
+++ b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note3/index.rst
@@ -0,0 +1,234 @@
+.. _mozilla_projects_nss_nss_tech_notes_nss_tech_note3:
+
+nss tech note3
+==============
+
+.. _all_about_certificate_extensions:
+
+`All About Certificate Extensions <#all_about_certificate_extensions>`__
+------------------------------------------------------------------------
+
+.. container::
+
+.. _nss_technical_note_3:
+
+`NSS Technical Note: 3 <#nss_technical_note_3>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ .. code::
+
+ 09 May 2002
+ Nelson B. Bolyard
+
+ This week at least 5 different people came to me with variants of the
+ same question:
+
+ What certificate extensions do I have to put into my cert for NSS to
+ allow it to be used for purpose <x>??
+
+ This message attempts to answer that question, and to document NSS's
+ approach to validating certificates for certain purposes.
+
+ When NSS is asked to verify the validity of a certificate chain, it
+ verifies the validity of that cert chain for a particular purpose,
+ known as a SECCertUsage, as of a specific date and time.
+
+ The list of known SECCertUsages is short:
+
+ certUsageSSLClient ........... An SSL client authentication cert
+ certUsageSSLServer ........... An ordinary SSL server cert
+ certUsageSSLServerWithStepUp.. An SSL server cert that allows export
+ clients to use strong crypto.
+ certUsageSSLCA ............... An intermediate or root CA cert allowed
+ to issue SSL client or SSL server certs
+ or other intermediate SSL CA certs.
+ certUsageEmailSigner ......... Used to verify S/MIME email signatures
+ certUsageEmailRecipient ...... Used to encrypt S/MIME emails.
+ certUsageObjectSigner ........ Used to verify signatures on files of
+ executable code, e.g. jar files.
+ certUsageStatusResponder ..... Used by an OCSP responder
+ certUsageVerifyCA ............ A CA of any kind.
+
+ Each cert has a "type" and a "key usage", each of which may contain one
+ or more valid values.
+
+ Each of the above SECCertUsages translates into a required set of
+ cert type and key usage for the certificate itself, and into another
+ set of required cert type and key usage for all the CA certs in the
+ cert chain.
+
+ To determine if a cert is valid for a given cert usage, it must have the
+ the cert type and key usage required for that cert usage, and all the
+ CA certs in the cert chain must have the cert type and key usage required
+ for CA certs for that cert usage.
+
+ There are 8 Key Usages:
+ CERT_SIGN
+ CRL_SIGN
+ DATA_ENCIPHERMENT
+ DIGITAL_SIGNATURE
+ GOVT_APPROVED
+ KEY_AGREEMENT
+ KEY_ENCIPHERMENT
+ NON_REPUDIATION
+
+ There are 9 Cert types:
+ EMAIL
+ EMAIL_CA
+ OBJECT_SIGNING
+ OBJECT_SIGNING_CA
+ SSL_CA
+ SSL_CLIENT
+ SSL_SERVER
+ STATUS_RESPONDER
+ TIME_STAMP
+
+
+ For the cert being checked, the requirements are:
+
+ Cert Usage Requried Key Usage Required Cert Type
+ -------------------- -------------------- -----------------------
+ SSLClient: DIGITAL_SIGNATURE; SSL_CLIENT;
+
+ SSLServer: KEY_AGREEMENT OR
+ KEY_ENCIPHERMENT; SSL_SERVER;
+
+ SSLServerWithStepUp: GOVT_APPROVED AND SSL_SERVER
+ KEY_AGREEMENT or
+ KEY_ENCIPHERMENT
+
+ SSLCA: CERT_SIGN; SSL_CA;
+
+ EmailSigner: DIGITAL_SIGNATURE; EMAIL;
+
+ EmailRecipient: KEY_AGREEMENT OR
+ KEY_ENCIPHERMENT; EMAIL;
+
+ ObjectSigner: DIGITAL_SIGNATURE; OBJECT_SIGNING;
+
+ StatusResponder: DIGITAL_SIGNATURE; STATUS_RESPONDER;
+
+ VerifyCA CERT_SIGN SSL_CA OR
+ EMAIL_CA OR
+ OBJECT_SIGNING_CA OR
+ STATUS_RESPONDER
+
+ For CA certs in the cert chain, the requirements are:
+
+ Cert Usage Requried Key Usage Required Cert Type
+ -------------------- -------------------- -----------------------
+ SSLServerWithStepUp: GOVT_APPROVED AND
+ CERT_SIGN; SSL_CA;
+
+ SSLClient: CERT_SIGN; SSL_CA;
+
+ SSLServer: CERT_SIGN; SSL_CA;
+
+ SSLCA: CERT_SIGN; SSL_CA;
+
+ EmailSigner: CERT_SIGN; EMAIL_CA or SSL_CA
+
+ EmailRecipient: CERT_SIGN; EMAIL_CA or SSL_CA
+
+ ObjectSigner: CERT_SIGN; OBJECT_SIGNING_CA;
+
+ UsageAnyCA: CERT_SIGN; OBJECT_SIGNING_CA OR
+ EMAIL_CA OR
+ SSL_CA;
+
+ StatusResponder: CERT_SIGN; OBJECT_SIGNING_CA OR
+ EMAIL_CA OR
+ SSL_CA;
+
+ Note: When the required key usage is KEY_AGREEMENT OR KEY_ENCIPHERMENT,
+ the actual key usage required depends on the key's algorithm. For
+ RSA keys, the required usage is KEY_ENCIPHERMENT. For other types of
+ keys, it is KEY_AGREEMENT.
+
+
+ Cert Extensions:
+
+ One vital Certificate extension is the "Basic Constraints" extension.
+ It tells NSS whether the cert is a CA cert, or not, and affects every
+ other aspect of how the cert is interpreted by NSS. The OID for this
+ extension is { 2 5 29 19 }, encoded in hex as 0x55, 0x1d, 0x13.
+ If the extension is present and has the value TRUE, then this cert is
+ taken to be a CA cert. Otherwise it is not (except that trust flags
+ may override this, see discussion of trust flags farther below).
+
+ Netscape has its own openly defined Cert Type extension, which can be used
+ to explicitly set the Cert Type in any Cert. The Cert Type extension has
+ bits in it that correspond directly to the cert types named above.
+ The OID for this extension is { 2 16 840 1 113730 1 1 }
+ encoded in hex as 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01
+
+ In addition to Netscape's own Cert Type extension, NSS recognizes various
+ X.509 extensions.
+
+ The X.509 key usage extension has OID { 2 5 29 0F } encoded in hex as
+ 0x55, 0x1d, 0x0f. If present, this extension directly determines the
+ values of the 8 key usages defined above. If absent, the cert is
+ assumed to be valid for all key usages.
+
+ The X.509v3 extended Key usage extension as OID { 2 5 29 37 } encoded in
+ hex as 0x55, 0x1d, 0x25. That extension contains a sequence of OIDs, each
+ of which signifies one or more Cert Types, depending on the presence or
+ absence of of the True Basic Constraints extension; that is, the
+ interpretation of the extended Key Usage extension is controlled by
+ whether the cert is a CA cert, or not.
+
+ The following table shows the OIDs recognized in the extended key usage
+ extension, and how they map to cert types and key usages for CA and non-CA
+ certs.
+
+ extended key usage OID non-CA cert CA cert
+ ----------------------------------- -------------- ----------------
+ SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT EMAIL_CA EMAIL_CA
+ SEC_OID_EXT_KEY_USAGE_SERVER_AUTH SSL_SERVER SSL_CA
+ SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH SSL_CLIENT SSL_CA
+ SEC_OID_EXT_KEY_USAGE_CODE_SIGN OBJECT_SIGNING OBJECT_SIGNING_CA
+ SEC_OID_EXT_KEY_USAGE_TIME_STAMP TIME_STAMP TIME_STAMP
+ SEC_OID_OCSP_RESPONDER OCSP_RESPONDER OCSP_RESPONDER
+
+ SEC_OID_NS_KEY_USAGE_GOVT_APPROVED GOVT_APPROVED GOVT_APPROVED
+
+ If the extended key usage extension is absent, the cert is assumed to have
+ the cert types SSL_CLIENT, SSL_SERVER and EMAIL, and if the cert is a CA
+ cert (as indicated by the presence of a true basic constraints extension),
+ the cert is also assumed to have the cert types SSL_CA, EMAIL_CA and
+ STATUS_RESPONDER. If the basic constraints extension is missing, but the
+ user has trusted the cert as a CA cert, the cert also gets the
+ STATUS_RESPONDER cert type. If the cert has a Fortezza type public key
+ with the magic bits that signify that it is a CA, it is given cert types
+ SSL_CA and EMAIL_CA.
+
+ A cert with the extended key usage extension and the Netscape cert type
+ extension that has the cert type SSL_CLIENT and also has an email address
+ in the subject is also given the cert type EMAIL. This allows all SSL
+ client authentication certs with email addresses to also be used as email
+ certs (provded they have adequate key usage).
+
+ A cert with the extended key usage extension and the Netscape cert type
+ extension that as cert type SSL_CA is also always given cert type EMAIL_CA.
+ This allows all SSL intermediate CAs to also be used as email intermediate CAs.
+
+ /* X.509 v3 Key Usage Extension flags */
+ #define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */
+ #define KU_NON_REPUDIATION (0x40) /* bit 1 */
+ #define KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */
+ #define KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */
+ #define KU_KEY_AGREEMENT (0x08) /* bit 4 */
+ #define KU_KEY_CERT_SIGN (0x04) /* bit 5 */
+ #define KU_CRL_SIGN (0x02) /* bit 6 */
+
+ #define NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */
+ #define NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */
+ #define NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */
+ #define NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */
+ #define NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */
+ #define NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */
+ #define NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */
+ #define NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */
+ </x> \ No newline at end of file
diff --git a/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note4/index.rst b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note4/index.rst
new file mode 100644
index 0000000000..7a7334bee2
--- /dev/null
+++ b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note4/index.rst
@@ -0,0 +1,221 @@
+.. _mozilla_projects_nss_nss_tech_notes_nss_tech_note4:
+
+nss tech note4
+==============
+
+.. _pulling_certificate_extension_information_out_of_ssl_certificates:
+
+`Pulling certificate extension information out of SSL certificates <#pulling_certificate_extension_information_out_of_ssl_certificates>`__
+------------------------------------------------------------------------------------------------------------------------------------------
+
+.. container::
+
+.. _nss_technical_note_4:
+
+`NSS Technical Note: 4 <#nss_technical_note_4>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ **Note:** This document contains code snippets that focus on essential aspects of the task and
+ often do not illustrate all the cleanup that needs to be done. Also, this document does not
+ attempt to be an exhaustive survey of all possible ways to do a certain task; it merely tries to
+ show a certain way.
+ .. rubric:: Include these files
+ :name: include_these_files
+
+ #include "ssl.h"
+ #include "cert.h"
+ .. rubric:: Get the handle of the cert associated with an SSL connection
+ :name: get_the_handle_of_the_cert_associated_with_an_ssl_connection
+
+ *CERTCertificate\* cert = SSL_PeerCertificate(PRFileDesc \*fd);*
+ If SSL client, this will get you the server's cert handle;
+ If SSL server, this will get you the client's cert handle IF client auth is enabled
+ *CERTCertificate\* cert = SSL_LocalCertificate(PRFileDesc \*fd);*
+ If SSL client, this will get you the client cert's handle, IF client auth happened
+ If SSL server, this will get you the server's cert handle
+ .. rubric:: Don't forget to clean up the cert handle when you're done with it
+ :name: don't_forget_to_clean_up_the_cert_handle_when_you're_done_with_it
+
+ *void CERT_DestroyCertificate(CERTCertificate \*cert);*
+ .. rubric:: Some info is readily available
+ :name: some_info_is_readily_available
+
+ cert->subjectName (char*)
+ cert->issuerName (char*)
+ cert->emailAddr (char*)
+ OR char \*CERT_GetCertificateEmailAddress(CERTCertificate \*cert);
+ cert->keyUsage (unsigned int)
+ .. rubric:: To break the issuer and subject names into components
+ :name: to_break_the_issuer_and_subject_names_into_components
+
+ Pass &(cert->issuer) or &(cert->subject) to the following functions
+ *char \*CERT_GetCommonName(CERTName \*name);
+ char \*CERT_GetCertEmailAddress(CERTName \*name);
+ char \*CERT_GetCountryName(CERTName \*name);
+ char \*CERT_GetLocalityName(CERTName \*name);
+ char \*CERT_GetStateName(CERTName \*name);
+ char \*CERT_GetOrgName(CERTName \*name);
+ char \*CERT_GetOrgUnitName(CERTName \*name);
+ char \*CERT_GetDomainComponentName(CERTName \*name);
+ char \*CERT_GetCertUid(CERTName \*name);*
+
+ Example code to illustrate access to the info is given below.
+ .. rubric:: Background on cert extensions
+ :name: background_on_cert_extensions
+
+ An extension has the following attributes
+
+ - Object Id (OID) : A unique OID represents an algorithm, a mechanism, a piece of information,
+ etc. Examples: X500 RSA Encryption, Certificate Basic Constraints, PKCS#7 Digested Data, etc.
+ There is a long list of pre-defined OIDs, and new ones can be *added dynamically by an
+ application.*
+ The OID data structure contains an array of identifier bytes (each byte is a "level" in a
+ hierarchical namespace), a text description, and some other things.
+ - Critical : indicates whether the extension is critical
+ - Value : The value of the extension
+
+ .. rubric:: Looping through all extensions
+ :name: looping_through_all_extensions
+
+ *CERTCertExtension*\* extensions =cert->extensions;*
+ *if (extensions)*
+ *{*
+ * while (*extensions)*
+ * {*
+ * SECItem \*ext_oid = &(*extensions)->id;*
+ * SECItem \*ext_critical = &(*extensions)->critical;*
+ * SECItem \*ext_value = &(*extensions)->value;*
+ * /\* id attribute of the extension \*/*
+ * SECOidData \*oiddata = SECOID_FindOID(ext_oid);*
+ * if (oiddata == NULL)*
+ * {*
+ */\* OID not found \*/*
+ */\* SECItem ext_oid has type (SECItemType), data (unsigned char \*) and len (unsigned int)
+ fields*
+ * - the application interprets these \*/*
+ *.......*
+ * }*
+ * else*
+ * {*
+ *char \*name = oiddata->desc; /\* name of the extension \*/*
+ *.......*
+ * }*
+ * /\* critical attribute of the extension \*/*
+ * if (ext_critical->len > 0)*
+ * {*
+ *if (ext_critical->data[0])*
+ * /\* the extension is critical \*/*
+ *else*
+ * /\* the extension is not critical \*/*
+ * }*
+ * /\* value attribute of the extension \*/*
+ * /\* SECItem ext_value has type (SECItemType), data (unsigned char \*) and len
+ (unsigned int) fields*
+ *- the application interprets these \*/*
+ * SECOidTag oidtag = SECOID_FindOIDTag(ext_oid);*
+ * switch (oidtag)*
+ * {*
+ *case a_tag_that_app_recognizes:*
+ * .....*
+ *case .....*
+ * ......*
+ * }*
+ * extensions++;*
+ * }*
+ *}*
+
+ .. rubric:: An example custom cert extension
+ :name: an_example_custom_cert_extension
+
+ *struct \_myCertExtData*
+ *{*
+ * SECItem version;*
+ * SECItem streetaddress;*
+ * SECItem phonenum;*
+ * SECItem rfc822name;*
+ * SECItem id;*
+ * SECItem maxusers;*
+ *};*
+ *typedef struct \_myCertExtData myCertExtData;*
+ */\* template used for decoding the extension \*/*
+ *const SEC_ASN1Template myCertExtTemplate[] = {*
+ * { SEC_ASN1_SEQUENCE, 0, NULL, sizeof( myCertExtData ) },*
+ * { SEC_ASN1_INTEGER, offsetof(myCertExtData, version) },*
+ * { SEC_ASN1_OCTET_STRING, offsetof( myCertExtData, streetaddress ) },*
+ * { SEC_ASN1_OCTET_STRING, offsetof( myCertExtData, phonenum ) },*
+ * { SEC_ASN1_OCTET_STRING, offsetof( myCertExtData, rfc822name ) },*
+ * { SEC_ASN1_OCTET_STRING, offsetof( myCertExtData, id ) },*
+ * { SEC_ASN1_INTEGER, offsetof(myCertExtData, maxusers ) },*
+ * { 0 }*
+ *};*
+ */\* OID for my cert extension - replace 0xff with appropriate values*/*
+ *static const unsigned char myoid[] = { 0xff, 0xff, 0xff, 0xff, .... };*
+ *static const SECItem myoidItem = { (SECItemType) 0, (unsigned char \*)myoid, sizeof(myoid)
+ };*
+ *SECItem myextvalue;
+ myCertExtData data;*
+ *SECStatus rv = CERT_FindCertExtensionByOID(cert, &myoidItem, &myextvalue);
+ if (rv == SECSuccess)
+ {
+ SEC_ASN1DecoderContext \* context = SEC_ASN1DecoderStart(NULL, &data, myCertExtTemplate);
+ rv = SEC_ASN1DecoderUpdate( context, (const char \*)(myextvalue.data), myextvalue.len);
+ if (rv == SECSuccess)
+ {
+ /\* Now you can extract info from SECItem fields of your extension data structure \*/
+ /\* See "Misc helper functions" below \*/
+ .......
+ /\* free the SECItem fields \*/
+ SECITEM_FreeItem(&data.version, PR_FALSE);
+ SECITEM_FreeItem(&data.streetaddress, PR_FALSE);
+ ......
+ SECITEM_FreeItem(&data.maxusers, PR_FALSE);
+ }
+ }*
+
+ .. rubric:: Some miscellaneous helper functions
+ :name: some_miscellaneous_helper_functions
+
+ - Compare two SECItems (e.g., two OIDs)
+ *PRBool SECITEM_ItemsAreEqual(const SECItem \*a, const SECItem \*b);*
+ - Interpreting a SECItem value as an integer
+ If SECItem \*item->len <=4, then int value = *DER_GetInteger(item)*;
+ - Interpreting a SECItem value as a string
+ Use string copy functions to copy item->len bytes from item->data and null terminate
+ explicitly
+
+ .. rubric:: Some higher level extension functions
+ :name: some_higher_level_extension_functions
+
+ - Get a specific extension from the list of extensions, given the extension tag
+ *SECStatus CERT_FindCertExtension (CERTCertificate \*cert, int tag, SECItem \*value);*
+ - Get a specific extension from the ISSUER's cert\ *
+ SECStatus CERT_FindIssuerCertExtension (CERTCertificate \*cert, int tag, SECItem \*value);*
+ - Get the value of an extension with the given OID
+ *SECStatus CERT_FindCertExtensionByOID (CERTCertificate \*cert, SECItem \*oid, SECItem
+ \*value);*
+ - Get the decoded value of the "Basic Constraints" extension
+ *SECStatus CERT_FindBasicConstraintExten (CERTCertificate \*cert, CERTBasicConstraints
+ \*value);*
+ - Get value of the keyUsage extension. This uses PR_Alloc to allocate buffer for the decoded
+ value, The caller should free up the storage allocated in value->data.
+ *SECStatus CERT_FindKeyUsageExtension (CERTCertificate \*cert, SECItem \*value);*
+ - Get decoded value of the subjectKeyID extension. This uses PR_Alloc to allocate buffer for
+ the decoded value, The caller should free up the storage allocated in value->data.
+ *SECStatus CERT_FindSubjectKeyIDExten (CERTCertificate \*cert, SECItem \*retItem);*
+
+ *
+ *
+
+.. _for_more_information:
+
+`For more information <#for_more_information>`__
+------------------------------------------------
+
+.. container::
+
+ - Browse through the NSS source code online at
+ http://lxr.mozilla.org/mozilla/source/security/nss/ and http://lxr.mozilla.org/security/
+ - documentation on some cert funcs
+ `http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslcrt.html <https://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslcrt.html>`__ \ No newline at end of file
diff --git a/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note5/index.rst b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note5/index.rst
new file mode 100644
index 0000000000..d9b7b9ddf6
--- /dev/null
+++ b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note5/index.rst
@@ -0,0 +1,659 @@
+.. _mozilla_projects_nss_nss_tech_notes_nss_tech_note5:
+
+nss tech note5
+==============
+
+.. _using_nss_to_perform_miscellaneous_cryptographic_operations:
+
+`Using NSS to perform miscellaneous cryptographic operations <#using_nss_to_perform_miscellaneous_cryptographic_operations>`__
+------------------------------------------------------------------------------------------------------------------------------
+
+.. container::
+
+.. _nss_technical_note_5:
+
+`NSS Technical Note: 5 <#nss_technical_note_5>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ - NSS Project Info is at
+ `http://www.mozilla.org/projects/security/pki/nss/ <https://www.mozilla.org/projects/security/pki/nss/>`__
+ - You can browse the NSS source online at http://lxr.mozilla.org/mozilla/source/security/nss/
+ and http://lxr.mozilla.org/security/
+ - Be sure to look for :ref:`mozilla_projects_nss_sample_code` first for things you need to do.
+ - **Note:** This document contains code snippets that focus on essential aspects of the task and
+ often do not illustrate all the cleanup that needs to be done. Also, this document does not
+ attempt to be an exhaustive survey of all possible ways to do a certain task; it merely tries
+ to show a certain way.
+
+ --------------
+
+`Encrypt/Decrypt <#encryptdecrypt>`__
+-------------------------------------
+
+.. container::
+
+ #. Include headers
+ *#include "nss.h"
+ #include "pk11pub.h"*
+ #. Make sure NSS is initialized.The simplest Init function, in case you don't need a NSS database
+ is
+ *NSS_NoDB_Init(".")*
+ #. Choose a cipher mechanism. Note that some mechanisms (*_PAD) imply the padding is handled for
+ you by NSS. If you choose something else, then data padding is the application's
+ responsibility. You can find a list of cipher mechanisms in security/nss/lib/softoken/pkcs11.c
+ - grep for CKF_EN_DE_.
+ *CK_MECHANISM_TYPE cipherMech = CKM_DES_CBC_PAD* <big>(for example)</big>
+ #. Choose a slot on which to do the operation
+ *PK11SlotInfo\* slot = PK11_GetBestSlot(cipherMech, NULL); *\ **OR**\ *
+ PK11SlotInfo\* slot = PK11_GetInternalKeySlot(); /\* alwys returns internal slot, may not be
+ optimal \*/*
+ #. Prepare the Key
+
+ - If using a raw key
+ */\* turn the raw key into a SECItem \*/
+ SECItem keyItem;
+ keyItem.data = /\* ptr to an array of key bytes \*/
+ keyItem.len = /\* length of the array of key bytes \*/
+ /\* turn the SECItem into a key object \*/
+ PK11SymKey\* SymKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap,
+
+ CKA_ENCRYPT, &keyItem, NULL)*;
+ - If generating the key - see section `Generate a Symmetric
+ Key <#generate_a_symmetric_key>`__
+
+
+ #. <big>Prepare the parameter for crypto context. IV is relevant only when using CBC mode of
+ encryption. If not using CBC mode, just pass a NULL IV parm to PK11_ParamFromIV function
+ *SECItem ivItem;
+ ivItem.data = /\* ptr to an array of IV bytes \*/
+ ivItem.len = /\* length of the array of IV bytes \*/
+ SECItem \*SecParam = PK11_ParamFromIV(cipherMech, &ivItem);*\ </big>
+ #. <big>Now encrypt and decrypt using the key and parameter setup in above steps</big>
+
+ - Create Encryption context
+ *PK11Context\* EncContext = PK11_CreateContextBySymKey(cipherMech,
+
+ CKA_ENCRYPT or CKA_DECRYPT,
+ SymKey,
+ SecParam);*
+ - Do the Operation. If encrypting, outbuf len must be atleast (inbuflen + blocksize). If
+ decrypting, outbuflen must be atleast inbuflen.
+ *SECStatus s = PK11_CipherOp(EncContext, outbuf, &tmp1_outlen, sizeof outbuf, inbuf,
+ inbuflen);
+ s = PK11_DigestFinal(EncContext, outbuf+tmp1_outlen, &tmp2_outlen,
+ sizeof outbuf - tmp1_outlen);
+ result_len = tmp1_outlen + tmp2_outlen;*
+ - <big>Destroy the Context
+ *PK11_DestroyContext(EncContext, PR_TRUE);*\ </big>
+
+ #. <big>Repeat Step 6 **any number of times**. When all done with encrypt/decrypt ops, clean
+ up</big>
+ <big>\ *PK11_FreeSymKey(SymKey);
+ SECITEM_FreeItem(SecParam, PR_TRUE);
+ PK11_FreeSlot(slot);*\ </big>
+
+ | **Note:** AES encryption, a fixed blocksize of 16 bytes is used. The Rijndael algorithm permits
+ 3 blocksizes (16, 24, 32 bytes), but the AES standard requires the blocksize to be 16 bytes.
+ The keysize can vary and these keysizes are permitted: 16, 24, 32 bytes.
+ | You can also look at a `sample program <../sample-code/sample2.html>`__ illustrating encryption
+
+ --------------
+
+.. _hash_digest:
+
+`Hash / Digest <#hash_digest>`__
+--------------------------------
+
+.. container::
+
+ #. Include headers
+ *#include "nss.h"
+ #include "pk11pub.h"*
+ #. Make sure NSS is initialized.The simplest Init function, in case you don't need a NSS database
+ is
+ *NSS_NoDB_Init(".")*
+ #. <big>Create Digest context</big>. Some of the digest algorithm identifiers are (without the
+ SEC_OID\_ prefix) : MD2, MD5, SHA1, SHA256, SHA384, SHA512.
+ *PK11Context\* DigestContext = PK11_CreateDigestContext(SEC_OID_MD5);*
+ #. <big>Digest the data</big>
+ <big>\ *SECStatus s = PK11_DigestBegin(DigestContext);
+ s = PK11_DigestOp(DigestContext, data, sizeof data);
+ s = PK11_DigestFinal(DigestContext, digest, &len, sizeof digest);
+ /\* now, digest contains the 'digest', and len contains the length of the digest \*/*\ </big>
+ #. Clean up
+ *PK11_DestroyContext(DigestContext, PR_TRUE);*
+
+ |
+ | You can also look at a `sample program <../sample-code/sample3.html>`__ illustrating this
+
+ --------------
+
+.. _hash_digest_with_secret_key_included:
+
+`Hash / Digest with secret key included <#hash_digest_with_secret_key_included>`__
+----------------------------------------------------------------------------------
+
+.. container::
+
+ #. Include headers
+ *#include "nss.h"
+ #include "pk11pub.h"*
+ #. Make sure NSS is initialized.The simplest Init function, in case you don't need a NSS database
+ is
+ *NSS_NoDB_Init(".")*
+ #. Choose a digest mechanism. You can find a list of digest mechanisms in
+ security/nss/lib/softoken/pkcs11.c - grep for CKF_DIGEST.
+ *CK_MECHANISM_TYPE digestMech = CKM_MD5* <big>(for example)</big>
+ #. Choose a slot on which to do the operation
+ *PK11SlotInfo\* slot = PK11_GetBestSlot(digestMech, NULL); *\ **OR**\ *
+ PK11SlotInfo\* slot = PK11_GetInternalKeySlot(); /\* always returns int slot, may not be
+ optimal \*/*
+ #. Prepare the Key
+
+ - If using a raw key
+ */\* turn the raw key into a SECItem \*/
+ SECItem keyItem;
+ keyItem.data = /\* ptr to an array of key bytes \*/
+ keyItem.len = /\* length of the array of key bytes \*/
+ /\* turn the SECItem into a key object \*/
+ PK11SymKey\* SymKey = PK11_ImportSymKey(slot, digestMech, PK11_OriginUnwrap,
+
+ CKA_DIGEST, &keyItem, NULL)*;
+ - If generating the key - see section `Generate a Symmetric
+ Key <#generate_a_symmetric_key>`__. Can use *CKM_GENERIC_SECRET_KEY_GEN* as the key gen
+ mechanism.
+
+
+ #. <big>Prepare the parameter for crypto context. The param must be provided, but can be empty.
+ *SECItem param;
+ param.data = 0;
+ param.len = 0;*\ </big>
+ #. <big>Create Crypto context</big>
+ *PK11Context\* DigestContext = PK11_CreateContextBySymKey(digestMech, CKA_DIGEST, SymKey,
+
+ &param);*
+ #. <big>Digest the data</big>, providing the key
+ <big>\ *SECStatus s = PK11_DigestBegin(DigestContext);
+ s = PK11_DigestKey(DigestContext, SymKey);
+ s = PK11_DigestOp(DigestContext, data, sizeof data);
+ s = PK11_DigestFinal(DigestContext, digest, &len, sizeof digest);
+ /\* now, digest contains the 'digest', and len contains the length of the digest \*/*\ </big>
+ #. Clean up
+ *PK11_DestroyContext(DigestContext, PR_TRUE);
+ PK11_FreeSymKey(SymKey);
+ PK11_FreeSlot(slot);*
+
+ You can also look at a `sample program <../sample-code/sample3.html>`__ illustrating this
+
+ --------------
+
+`HMAC <#hmac>`__
+----------------
+
+.. container::
+
+ #. Include headers
+ *#include "nss.h"
+ #include "pk11pub.h"*
+ #. Make sure NSS is initialized.The simplest Init function, in case you don't need a NSS database
+ is
+ *NSS_NoDB_Init(".")*
+ #. Choose a HMAC mechanism. You can find a list of HMAC mechanisms in
+ security/nss/lib/softoken/pkcs11.c - grep for CKF_SN_VR, and choose the mechanisms that
+ contain HMAC in the name
+ *CK_MECHANISM_TYPE hmacMech = CKM_MD5_HMAC;* <big>(for example)</big>
+ #. Choose a slot on which to do the operation
+ *PK11SlotInfo\* slot = PK11_GetBestSlot(hmacMech, NULL); *\ **OR**\ *
+ PK11SlotInfo\* slot = PK11_GetInternalKeySlot(); /\* always returns int slot, may not be
+ optimal \*/*
+ #. Prepare the Key
+
+ - If using a raw key
+ */\* turn the raw key into a SECItem \*/
+ SECItem keyItem;
+ keyItem.type = siBuffer;
+ keyItem.data = /\* ptr to an array of key bytes \*/
+ keyItem.len = /\* length of the array of key bytes \*/
+ /\* turn the SECItem into a key object \*/
+ PK11SymKey\* SymKey = PK11_ImportSymKey(slot, hmacMech, PK11_OriginUnwrap,
+
+ CKA_SIGN, &keyItem, NULL)*;
+ - If generating the key - see section `Generate a Symmetric
+ Key <#generate_a_symmetric_key>`__. Can use *CKM_GENERIC_SECRET_KEY_GEN* as the key gen
+ mechanism.
+
+
+ #. <big>Prepare the parameter for crypto context. The param must be provided, but can be empty.
+ *SECItem param;
+ param.type = siBuffer;
+ param.data = NULL;
+ param.len = 0;*\ </big>
+ #. <big>Create Crypto context</big>
+ *PK11Context\* DigestContext = PK11_CreateContextBySymKey(hmacMech, CKA_SIGN,
+
+ SymKey, &param);*
+ #. <big>Digest the data</big>
+ <big>\ *SECStatus s = PK11_DigestBegin(DigestContext);
+ s = PK11_DigestOp(DigestContext, data, sizeof data);
+ s = PK11_DigestFinal(DigestContext, digest, &len, sizeof digest);
+ /\* now, digest contains the 'signed digest', and len contains the length of the digest
+ \*/*\ </big>
+ #. Clean up
+ *PK11_DestroyContext(DigestContext, PR_TRUE);*
+ *PK11_FreeSymKey(SymKey);
+ PK11_FreeSlot(slot);*
+
+ |
+ | You can also look at a `sample program <../sample-code/sample3.html>`__ illustrating this
+
+ --------------
+
+.. _symmetric_key_wrappingunwrapping_of_a_symmetric_key:
+
+`Symmetric Key Wrapping/Unwrapping of a Symmetric Key <#symmetric_key_wrappingunwrapping_of_a_symmetric_key>`__
+---------------------------------------------------------------------------------------------------------------
+
+.. container::
+
+ #. Include headers
+ *#include "nss.h"
+ #include "pk11pub.h"*
+ #. Make sure NSS is initialized.The simplest Init function, in case you don't need a NSS database
+ is
+ *NSS_NoDB_Init(".")*
+ #. Choose a Wrapping mechanism. See wrapMechanismList in security/nss/lib/pk11wrap/pk11slot.c
+ and security/nss/lib/ssl/ssl3con.c for examples of wrapping mechanisms. Most of them are
+ cipher mechanisms.
+ *CK_MECHANISM_TYPE wrapMech = CKM_DES3_ECB;* <big>(for example)</big>
+ #. Choose a slot on which to do the operation
+ *PK11SlotInfo\* slot = PK11_GetBestSlot(wrapMech, NULL); *\ **OR**\ *
+ PK11SlotInfo\* slot = PK11_GetInternalKeySlot(); /\* always returns int slot, may not be
+ optimal \*/*
+ <big>Regarding the choice of slot and wrapMech, if you know one, you can derive the other. You
+ can get the best slot given a wrap mechanism (as shown above), or get the best wrap mechanism
+ given a slot using:</big>
+ *CK_MECHANISM_TYPE wrapMech = PK11_GetBestWrapMechanism(slot)*
+ #. Prepare the Wrapping Key
+
+ - If using a raw key
+ */\* turn the raw key into a SECItem \*/
+ SECItem keyItem;
+ keyItem.data = /\* ptr to an array of key bytes \*/
+ keyItem.len = /\* length of the array of key bytes \*/
+ /\* turn the SECItem into a key object \*/
+ PK11SymKey\* WrappingSymKey = PK11_ImportSymKey(slot, wrapMech,
+
+ PK11_OriginUnwrap,
+
+ CKA_WRAP, &keyItem, NULL)*
+
+ - If generating the key - see section `Generate a Symmetric
+ Key <#generate_a_symmetric_key>`__
+
+
+ #. Prepare the To-be-Wrapped Key
+
+ - If using a raw key
+ */\* turn the raw key into a SECItem \*/
+ SECItem keyItem;
+ keyItem.data = /\* ptr to an array of key bytes \*/
+ keyItem.len = /\* length of the array of key bytes \*/
+ /\* turn the SECItem into a key object \*/
+ PK11SymKey\* ToBeWrappedSymKey = PK11_ImportSymKey(slot, wrapMech,,
+
+ PK11_OriginUnwrap,
+
+ CKA_WRAP, &keyItem, NULL)*;
+ - If generating the key - see section `Generate a Symmetric
+ Key <#generate_a_symmetric_key>`__
+
+
+ #. <big>Prepare the parameter for crypto context. IV is relevant only when using CBC cipher mode.
+ If not using CBC mode, just pass a NULL *SecParam* to *PK11_WrapSymKey* or *PK11_UnwrapSymKey*
+ function
+ *SECItem ivItem;
+ ivItem.data = /\* ptr to an array of IV bytes \*/
+ ivItem.len = /\* length of the array of IV bytes \*/
+ SECItem \*SecParam = PK11_ParamFromIV(wrapMech, &ivItem);*\ </big>
+ #. Allocate space for the wrapped key
+ *SECItem WrappedKey;
+ WrappedKey.len = SOME_LEN;
+ WrappedKey.data = allocate (SOME_LEN) bytes;*
+ #. <big>Do the Wrap</big>. Note that the WrappingSymKey and the ToBeWrappedSymKey must be on the
+ slot where the wrap is going to happen. To move keys to the desired slot, see section `Moving
+ a Key from one slot to another <#moving_a_key_from_one_slot_to_another>`__
+ <big>\ *SECStatus s = PK11_WrapSymKey(wrapMech, SecParam, WrappingSymKey,
+ ToBeWrappedSymKey,
+ &WrappedKey);*\ </big>
+ #. <big><big>Transport/Store or do whatever with the Wrapped Key (WrappedKey.data,
+ WrappedKey.len)</big></big>
+ #. <big><big>Unwrapping. </big></big>
+
+ - <big><big>Set up the args to the function *PK11_UnwrapSymKey*, most of which are
+ illustrated above. The *keyTypeMech* arg of type *CK_MECHANISM_TYPE *\ <big>indicates the
+ type of key that was wrapped and can be same as the *wrapMech* (e.g.
+ *wrapMech=CKM_SKIPJACK_WRAP, keyTypeMech=CKM_SKIPJACK_CBC64; wrapMech=CKM_SKIPJACK_CBC64,
+ keyTypeMech=CKM_SKIPJACK_CBC64*).</big>\ </big></big>
+ - Do the unwrap
+ <big><big>\ *PK11SymKey\* UnwrappedSymKey = PK11_UnwrapSymKey(WrappingSymKey,
+
+ wrapMech*\ </big></big><big><big>\ *, SecParam, &WrappedKey,
+
+ keyTypeMech,*\ </big></big>
+ <big><big>\ *
+ CKA_UNWRAP, /\* or CKA_DECRYPT? \*/
+
+ size_of_key_that_was_wrapped_bytes);*\ </big></big>
+
+ #. Clean up
+ *PK11_FreeSymKey(WrappingSymKey);*
+ *PK11_FreeSymKey(ToBeWrappedSymKey);
+ PK11_FreeSymKey(UnwrappedSymKey);
+ if (SecParam) SECITEM_FreeItem(SecParam, PR_TRUE);
+ SECITEM_FreeItem(&WrappedKey, PR_TRUE);
+ PK11_FreeSlot(slot); *
+
+ --------------
+
+.. _symmetric_key_wrappingunwrapping_of_a_private_key:
+
+`Symmetric Key Wrapping/Unwrapping of a Private Key <#symmetric_key_wrappingunwrapping_of_a_private_key>`__
+-----------------------------------------------------------------------------------------------------------
+
+.. container::
+
+ #. Include headers
+ *#include "nss.h"
+ #include "pk11pub.h"*
+ #. Make sure NSS is initialized.
+ #. Choose a Wrapping mechanism. See wrapMechanismList in security/nss/lib/pk11wrap/pk11slot.c
+ and security/nss/lib/ssl/ssl3con.c for examples of wrapping mechanisms. Most of them are
+ cipher mechanisms.
+ *CK_MECHANISM_TYPE wrapMech = CKM_DES3_ECB;* <big>(for example).</big>
+ #. Slot on which to do the operation
+ *PK11SlotInfo\* slot = PK11_GetBestSlot(wrapMech, NULL); *\ **OR**\ *
+ PK11SlotInfo\* slot = PK11_GetInternalKeySlot(); /\* always returns int slot, may not be
+ optimal \*/*
+ This should be the slot that is best suited for the wrapping. This may or may not be the slot
+ that contains the private key or the slot that contains the Symmetric key.
+ <big>Regarding the choice of slot and wrapMech, if you know one, you can derive the other. You
+ can get the best slot given a wrap mechanism (as shown above), or get the best wrap mechanism
+ given a slot using:</big>
+ *CK_MECHANISM_TYPE wrapMech = PK11_GetBestWrapMechanism(slot)*
+ #. Prepare the Wrapping Key
+
+ - If using a raw key
+ */\* turn the raw key into a SECItem \*/
+ SECItem keyItem;
+ keyItem.data = /\* ptr to an array of key bytes \*/
+ keyItem.len = /\* length of the array of key bytes \*/
+ /\* turn the SECItem into a key object \*/
+ PK11SymKey\* WrappingSymKey = PK11_ImportSymKey(slot, wrapMech,
+
+ PK11_OriginUnwrap,
+
+ CKA_WRAP, &keyItem, NULL)*;
+ - If generating the key - see section `Generate a Symmetric
+ Key <#generate_a_symmetric_key>`__
+
+
+ #. Prepare the To-be-Wrapped Key
+
+ - *SECKEYPrivateKey \*ToBeWrappedPrivKey *
+
+ #. <big>Prepare the parameter for crypto context. IV is relevant only when using CBC cipher mode.
+ If not using CBC mode, just pass a NULL *SecParam* to *PK11_WrapPrivKey* function
+ *SECItem ivItem;
+ ivItem.data = /\* ptr to an array of IV bytes \*/
+ ivItem.len = /\* length of the array of IV bytes \*/
+ SECItem \*SecParam = PK11_ParamFromIV(wrapMech, &ivItem);*\ </big>
+ #. Allocate space for the wrapped key. Note that a 2048-bit *wrapped* RSA private key takes up
+ around 1200 bytes.
+ *SECItem WrappedKey;
+ WrappedKey.len = SOME_LEN;
+ WrappedKey.data = allocate (SOME_LEN) bytes;*
+ #. <big>Do the Wrap</big>. Note that the WrappingSymKey and the ToBeWrappedPvtKey must be on the
+ slot where the wrap is going to happen. To move keys to the desired slot, see section `Moving
+ a Key from one slot to another <#moving_a_key_from_one_slot_to_another>`__
+ <big>\ *SECStatus s = PK11_WrapPrivKey(slot, WrappingSymKey, ToBeWrappedPvtKey, wrapMech,
+ SecParam, &WrappedKey,
+ NULL);*\ </big>
+ #. <big><big>Transport/Store or do whatever with the Wrapped Key (WrappedKey.data,
+ WrappedKey.len)</big></big>
+ #. <big><big>Unwrapping.</big></big>
+
+ - Prepare the args for the unwrap function. Most of the args are illustrated above
+ *SECItem label; /\* empty, doesn't need to be freed \*/
+ label.data = NULL; label.len = 0;*
+ *SECItem \*pubValue = NULL;
+ pubValue = /\* ?? \*/;*
+ *PRBool token = /\* PR_TRUE or PR_FALSE depending on?? \*/
+ CK_MECHANISM_TYPE keyTypeMech = ??;
+ CK_KEY_TYPE keyType;
+ keyType = PK11_GetKeyType(keyTypeMech, 0);
+ CK_ATTRIBUTE_TYPE attribs[4];
+ int numAttribs;
+ /\* figure out which operations to enable for this key \*/
+ if( keyType == CKK_RSA ) {
+ attribs[0] = CKA_SIGN;
+ attribs[1] = CKA_DECRYPT;
+ attribs[2] = CKA_SIGN_RECOVER;
+ attribs[3] = CKA_UNWRAP;
+ numAttribs = 4;
+ } else if(keyType == CKK_DSA) {
+ attribs[0] = CKA_SIGN;
+ numAttribs = 1;
+ }*
+ - <big>Do the unwrap</big>
+ *SECKEYPrivateKey \*UnwrappedPvtKey =
+ PK11_UnwrapPrivKey(slot, WrappingSymKey, wrapMech, SecParam, &WrappedKey,
+ &label, pubValue, token, PR_TRUE
+ /\* sensitive \*/
+ keyType, attribs, numAttribs,
+ NULL /*wincx*/);*
+
+ #. Clean up
+ *PK11_FreeSymKey(WrappingSymKey);*
+ <big>\ *if (SecParam) SECITEM_FreeItem(SecParam, PR_TRUE);*\ </big>
+ <big>\ *SECITEM_FreeItem(&WrappedKey, PR_TRUE);*\ </big>
+ *if (pubValue) SECITEM_FreeItem(pubValue, PR_TRUE);*
+ *if (UnwrappedPvtKey) SECKEY_DestroyPrivateKey(UnwrappedPvtKey);*
+ *if (ToBeWrappedPvtKey) SECKEY_DestroyPrivateKey(ToBeWrappedPvtKey);*
+ *PK11_FreeSlot(slot);*
+
+ --------------
+
+.. _public_key_wrapping_private_key_unwrapping_of_a_symmetric_key_(pki_based_key_transport):
+
+`Public Key Wrapping & Private Key Unwrapping of a Symmetric Key (PKI based key transport) <#public_key_wrapping_private_key_unwrapping_of_a_symmetric_key_(pki_based_key_transport)>`__
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+.. container::
+
+ #. Include headers
+ *#include "nss.h"
+ #include "pk11pub.h"*
+ #. Make sure NSS is initialized.
+ #. Choose a Wrapping mechanism. See wrapMechanismList in security/nss/lib/pk11wrap/pk11slot.c
+ and security/nss/lib/ssl/ssl3con.c for examples of wrapping mechanisms. Most of them are
+ cipher mechanisms.
+ *CK_MECHANISM_TYPE wrapMech = CKM_DES3_ECB;* <big>(for example)</big>
+ #. Slot on which to do the operation
+ *PK11SlotInfo\* slot = PK11_GetBestSlot(wrapMech, NULL); *\ **OR**\ *
+ PK11SlotInfo\* slot = PK11_GetInternalKeySlot(); /\* always returns int slot, may not be
+ optimal \*/*
+ This should be the slot that is best suited for the wrapping. This may or may not be the slot
+ that contains the public/private key or the slot that contains the Symmetric key.
+ <big>Regarding the choice of slot and wrapMech, if you know one, you can derive the other. You
+ can get the best slot given a wrap mechanism (as shown above), or get the best wrap mechanism
+ given a slot using:</big>
+ *CK_MECHANISM_TYPE wrapMech = PK11_GetBestWrapMechanism(slot)*
+ #. Prepare the Wrapping Key
+
+ - *SECKeyPublicKey \*WrappingPubKey*
+
+ #. Prepare the To-be-Wrapped Key
+
+ - If using a raw key
+ */\* turn the raw key into a SECItem \*/
+ SECItem keyItem;
+ keyItem.data = /\* ptr to an array of key bytes \*/
+ keyItem.len = /\* length of the array of key bytes \*/
+ /\* turn the SECItem into a key object \*/
+ PK11SymKey\* ToBeWrappedSymKey = PK11_ImportSymKey(slot, wrapMech,,
+
+ PK11_OriginUnwrap,
+
+ CKA_WRAP, &keyItem, NULL)*;
+ - If generating the key - see section `Generate a Symmetric
+ Key <#generate_a_symmetric_key>`__
+
+ #. Allocate space for the wrapped key
+ *SECItem WrappedKey;
+ WrappedKey.len = SOME_LEN;
+ WrappedKey.data = allocate (SOME_LEN) bytes;*
+ #. <big>Do the Wrap</big>. Note that the WrappingPubKey and the ToBeWrappedSymKey must be on the
+ slot where the wrap is going to happen. To move keys to the desired slot, see section `Moving
+ a Key from one slot to another <#moving_a_key_from_one_slot_to_another>`__
+ <big>\ *SECStatus s = PK11_PubWrapSymKey(wrapMech, WrappingPubKey,
+ ToBeWrappedSymKey,
+ &WrappedKey);*\ </big>
+ #. <big><big>Transport/Store or do whatever with the Wrapped Key (WrappedKey.data,
+ WrappedKey.len)</big></big>
+ #. <big><big>Unwrapping. </big></big>
+
+ - Prepare the args for the unwrap function. Most of the args are illustrated above
+ *SECKEYPrivateKey \*UnWrappingPvtKey;
+ CK_MECHANISM_TYPE keyTypeMech = ??;*
+ - <big>Do the unwrap</big>
+ *PK11SymKey \*UnwrappedSymKey =
+ PK11_PubUnwrapSymKey(UnWrappingPvtKey, WrappedKey, keyTypeMech,
+ *<big><big>\ *CKA_UNWRAP, /\*
+ or CKA_DECRYPT? \*/
+
+ *\ </big></big><big><big>\ *size_of_key_that_was_wrapped_bytes);*\ </big></big>
+
+ #. Clean up
+ *PK11_FreeSymKey(ToBeWrappedSymKey);*
+ <big>\ *SECITEM_FreeItem(&WrappedKey, PR_TRUE);*\ </big>
+ *if (WrappingPubKey) SECKEY_DestroyPublicKey(WrappingPubKey);*
+ *if (UnwrappingPvtKey) SECKEY_DestroyPrivateKey(UnwrappingPvtKey);*
+ *PK11_FreeSlot(slot);*
+
+ Also look at a `sample program <../sample-code/sample1.html>`__ that uses the above functions.
+
+ --------------
+
+.. _generate_a_symmetric_key_2:
+
+`Generate a Symmetric Key <#generate_a_symmetric_key_2>`__
+----------------------------------------------------------
+
+.. container::
+
+ | Subsequent to the operation, the symmetric key may need to be transported/stored in wrapped or
+ raw form. You can find a list of key generation mechanisms in
+ security/nss/lib/softoken/pkcs11.c - grep for CKF_GENERATE. For some key gen mechanisms, the
+ keysize is in bytes, and for some it is in bits.
+ |
+
+ #. <big>Choose a key generation mechanism</big>
+ *CK_MECHANISM_TYPE keygenMech = CKM_DES_KEY_GEN;* (for example)
+ #. <big>Generate the key</big>
+ *PK11SymKey\* SymKey = PK11_KeyGen(slot, keygenMech, NULL, keysize, NULL);*
+
+ <big>You can also see an `sample program <../sample-code/sample1.html>`__ that does key
+ generation.</big>
+
+ .. rubric:: Extract the raw key (This should not normally be used. Better to use wrapping
+ instead. See `method1 <#symmetric_key_wrappingunwrapping_sym_key>`__ and
+ `method2 <#pki_wrap_symkey>`__ ).
+ :name: extract_the_raw_key_(this_should_not_normally_be_used._better_to_use_wrapping_instead._see_method1_and_method2_).
+
+ *SECStatus rv = PK11_ExtractKeyValue(SymKey);
+ SECItem \*keydata = PK11_GetKeyData(SymKey);*
+
+ .. rubric:: Generating a persistent symmetric key
+ :name: generating_a_persistent_symmetric_key
+
+ | *SECItem keyid;
+ CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC_PAD;
+ keyid.data = /\* ptr to an array of bytes representing the id of the key to be generated \*/;
+ keyid.len = /\* length of the array of bytes \*/;
+ /\* keysize must be 0 for fixed key-length algorithms like DES... and appropriate value
+ \* for non fixed-key-length algorithms \*/
+ PK11SymKey \*key = PK11_TokenKeyGen(slot, cipherMech, 0, 32 /\* keysize \*/,
+ &keyid, PR_TRUE,
+ 0);*
+ | *int keylen = PK11_GetKeyLength(key);
+ cipherMech = PK11_GetMechanism(key);*
+ | */\* find the symmetric key in the database \*/
+ key = PK11_FindFixedKey(slot, cipherMech, &keyid, 0);*
+
+ --------------
+
+.. _moving_a_key_from_one_slot_to_another_2:
+
+`Moving a Key from one slot to another <#moving_a_key_from_one_slot_to_another_2>`__
+------------------------------------------------------------------------------------
+
+.. container::
+
+ - To move a Private key from one slot to another, wrap the private key on the origin slot and
+ unwrap it into the destination slot. See section `Symmetric Key Wrapping/Unwrapping of a
+ Private Key <#symmetric_key_wrappingunwrapping_pvtkey>`__
+ - To move a Symmetric key
+ *PK11SymKey \*destSymKey = pk11_CopyToSlot(destslot, wrapMech, CKA_UNWRAP?, origSymKey);*
+
+ --------------
+
+.. _generate_an_rsa_key_pair:
+
+`Generate an RSA Key Pair <#generate_an_rsa_key_pair>`__
+--------------------------------------------------------
+
+.. container::
+
+ *PK11_GenerateKeyPair*\ <big> is the function to use</big>. See a `sample
+ program <../sample-code/sample1.html>`__ that uses this function.
+
+ --------------
+
+.. _<big>sign_verify_data<big>:
+
+`<big>Sign & Verify Data</big> <#%3Cbig%3Esign_verify_data%3Cbig%3E>`__
+-----------------------------------------------------------------------
+
+.. container::
+
+ | *SECKEYPrivateKey \*pvtkey;
+ SECItem signature;
+ SECItem data;
+ SECStatus s = PK11_Sign(pvtkey, &signature, &data);*
+ | *SECKeyPublicKey \*pubkey;*
+ | *SECStatus s = PK11_Verify(pubkey, &signature, &data, NULL);*
+
+ --------------
+
+.. _misc_useful_functions:
+
+`Misc Useful Functions <#misc_useful_functions>`__
+--------------------------------------------------
+
+.. container::
+
+ #. Get the best wrapping mechanism supported by a slot
+ *CK_MECHANISM_TYPE mech = PK11_GetBestWrapMechanism(PK11SlotInfo \*slot);*
+ #. <big>Get the best slot for a certain mechanism</big>
+ *PK11SlotInfo\* slot = PK11_GetBestSlot(mechanism, NULL);*
+ #. <big>Get the best key length for a certain mechanism on a given slot</big>
+ *int keylen = PK11_GetBestKeyLength(PK11SlotInfo \*slot, mechanism);*
+ #. Get the key length of a symmetric key
+ *int keylen = PK11_GetKeyLength(PK11SymKey \*symkey);*
+ #. Get the mechanism given a symmetric key
+ *CK_MECHANISM_TYPE mech = PK11_GetMechanism(PK11SymKey \*key);*
+
+
+ -------------- \ No newline at end of file
diff --git a/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note6/index.rst b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note6/index.rst
new file mode 100644
index 0000000000..a55425c752
--- /dev/null
+++ b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note6/index.rst
@@ -0,0 +1,104 @@
+.. _mozilla_projects_nss_nss_tech_notes_nss_tech_note6:
+
+nss tech note6
+==============
+
+.. _nss_.chk_files_for_the_fips_140_mode:
+
+`NSS .chk Files for the FIPS 140 Mode
+ <#nss_.chk_files_for_the_fips_140_mode>`__
+-------------------------------------------
+
+.. container::
+
+.. _nss_technical_note_6:
+
+`NSS Technical Note: 6 <#nss_technical_note_6>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ In NSS 3.8, we added checksum files required for the NSS softoken to operate in FIPS 140 mode.
+ The new checksum file is called libsoftokn3.chk on Unix/Linux and softokn3.chk on Windows. It
+ must be put in the same directory as the NSS libraries. The libsoftokn3.chk/softokn3.chk file
+ contains a checksum for the softoken. When in FIPS 140 mode, the softoken is required to compute
+ its checksum and compare it with the value in libsoftokn3.chk/softokn3.chk.
+
+ The following applies to NSS 3.8 through 3.10 :
+
+ | On 32-bit Solaris SPARC (i.e., not x86, and not 64-bit SPARC) and 32-bit HP-UX PA-RISC (i.e.,
+ not Itanium, and not 64-bit PA-RISC), there are two more .chk files: libfreebl_pure32_3.chk and
+ libfreebl_hybrid_3.chk.
+ |
+
+ The following applies to NSS 3.11 :
+
+ The low-level freebl cryptographic code has been separated from softoken on all platforms. Even
+ on platforms for which there is only one implementation of freebl, there is now a separate freebl
+ shared library. The freebl library implements a private interface internal to NSS.
+
+ - On 32-bit Windows and 32-bit OS/2, this shared library is called freebl3.dll, and the
+ corresponding .chk file is called freebl3.chk .
+ - On 32-bit Solaris x86, 64-bit Solaris x64 (AMD64), 32-bit Linux x86, 64-bit Linux x86-64,
+ 32-bit AIX and 64-bit AIX, this shared library is called libfreebl3.so, and the corresponding
+ .chk file is called libfreebl3.chk .
+ - On the 32-bit Solaris SPARC architecture, there are 3 freebl libraries :
+
+ - libfreebl_32int64_3.so for UltraSparc T1 CPUs, with a corresponding libfreebl_32int64_3.chk
+ - libfreebl_32fpu_3.so for other UltraSparc CPUs, with a corresponding libfreebl_32fpu_3.chk
+ - libfreebl_32int_3.so for SPARC V8 CPUs, with a corresponding libfreebl_32int_3.chk
+
+ - On the 64-bit Solaris SPARC architecture, there are 2 freebl libraries :
+
+ - libfreebl_64int_3.so for UltraSparc T1 CPUs, with a corresponding libfreebl_64int_3.chk
+ - libfreebl_64fpu_3.so for other UltraSparc CPUs, with a corresponding libfreebl_64fpu_3.chk
+
+ - On the 32-bit HP-UX PA-RISC architecture, there are 2 freebl libraries :
+
+ - libfreebl_32fpu_3.sl for CPUs that do multiply operations faster in floating point, with a
+ corresponding libfreebl_32fpu_3.chk
+ - libfreebl_32int_3.sl for other PA-RISC CPUs, with a corresponding libfreebl_32int_3.chk
+
+ - On the 64-bit HP-UX PA-RISC architecture, there is only one freebl library, called
+ libfreebl3.sl, with a corresponding libfreebl3.chk
+
+ Applications should always use NSS binaries that are the output of the regular NSS build process.
+ If your application modifies NSS binaries for any reason after they were built, then :
+
+ - The FIPS 140 mode of operation will no longer work, because the chk files will no longer match
+ the softoken and freebl shared libraries .
+ - The softoken and freebl binaries won't match any NSS binaries that may have been submitted to
+ NIST for validation, and thus may not be verified as being the actual FIPS 140 validated
+ cryptographic module . The only way to meet this requirement is for your application never to
+ modify the NSS binaries.
+ - Any offer of binary support that may have been previously made to you by NSS developers is
+ null and void.
+
+ If your build process modifies NSS libraries in any way (for example, to strip the symbols), it
+ should consider not doing so for the reasons cited above. If you still decide to make unsupported
+ changes, you can allow the softoken to come up in FIPS 140 mode of operation by regenerating the
+ .chk files yourself. The tool to do that is called shlibsign. It is released as part of the NSS
+ binary distributions.
+ If your build process does not modify NSS shared libraries, you can just use the .chk files in
+ the NSS binary distributions.
+
+ So you have two options.
+
+ 1. Do not modify NSS libraries in your build process. Specifically, do not modify libsoftokn3.so,
+ libsoftokn3.sl, softokn3.dll, libfreebl_pure32_3.so, libfreebl_pure32_3.sl,
+ libfreebl_hybrid_3.so,libfreebl_hybrid_3.sl, libfreebl3.so, libfreebl3.sl, freebl3.dll,
+ libfreebl_32int64_3.so, libfreebl_32int_3.so, libfreebl_32fpu_3.so, libfreebl_64int_3.so,
+ libfreebl_64fpu_3.so, libfreebl_32int_3.sl, libfreebl_32fpu_3.sl; or
+
+ 2. Use shlibsign to regenerate the .chk files. For example, on 32-bit Solaris SPARC for NSS
+ 3.11, say
+
+ shlibsign -v -i libsoftokn3.so
+ shlibsign -v -i libfreebl_32int64_3.so
+ shlibsign -v -i libfreebl_32fpu_3.so
+ shlibsign -v -i libfreebl_32int_3.so
+
+ (You need to set LD_LIBRARY_PATH appropriately and specify the correct pathnames of the
+ libraries.)
+
+ Option 1 is simpler and highly preferred. \ No newline at end of file
diff --git a/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note7/index.rst b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note7/index.rst
new file mode 100644
index 0000000000..f7fa00f6d9
--- /dev/null
+++ b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note7/index.rst
@@ -0,0 +1,189 @@
+.. _mozilla_projects_nss_nss_tech_notes_nss_tech_note7:
+
+nss tech note7
+==============
+
+.. _rsa_signing_and_encryption_with_nss:
+
+`RSA Signing and Encryption with NSS <#rsa_signing_and_encryption_with_nss>`__
+------------------------------------------------------------------------------
+
+.. container::
+
+.. _nss_technical_note_7:
+
+`NSS Technical Note: 7 <#nss_technical_note_7>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ This technical note explains how to use NSS to perform RSA signing and encryption. The industry
+ standard for RSA signing and encryption is `PKCS
+ #1 <http://www.rsasecurity.com/rsalabs/node.asp?id=2125>`__. NSS supports PKCS #1 v1.5. NSS
+ doesn't yet support PKCS #1 v2.0 and v2.1, in particular OAEP, but OAEP support is on our `to-do
+ list <https://bugzilla.mozilla.org/show_bug.cgi?id=158747>`__. Your contribution is welcome.
+
+.. _data_types:
+
+`Data Types <#data_types>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ NSS uses the following data types to represent keys:
+
+ - ``SECKEYPublicKey``: a public key, defined in "keythi.h".
+ - ``SECKEYPrivateKey``: a private key, defined in "keythi.h".
+ - ``PK11SymKey``: a symmetric key (often called a session key), defined in "secmodt.h".
+
+ | These data types should be used as if they were opaque structures, that is, they should only be
+ created by some NSS functions and you always pass pointers to these data types to NSS functions
+ and never examine the members of these structures.
+ | The strength of an RSA key pair is measured by the size of its modulus because given the
+ modulus and public exponent, the best known algorithm for computing the private exponent is to
+ factor the modulus. At present 1024 bit and 2048 bit RSA keys are the most common and
+ recommended. To prevent denial-of-service attacks with huge public keys, NSS disallows modulus
+ size greater than 8192 bits.
+ | How are these keys created in NSS? There are a few possibilities.
+
+ - RSA key pairs may be generated inside a crypto module (also known as a token). Use
+ ``PK11_GenerateKeyPair()`` to generate a key pair in a crypto module.
+
+ - Key pairs may be generated elsewhere, exported in encrypted form, and imported into a crypto
+ module.
+
+ - | Public keys may be imported into NSS. Call ``SECKEY_ImportDERPublicKey()`` with
+ ``type=CKK_RSA`` to import a DER-encoded RSA public key. If you have the modulus and public
+ exponent, you need to first encode them into an RSA public key and then import the public
+ key into NSS.
+ | PKCS #1 defines an RSA public key as a ``SEQUENCE`` of modulus and public exponent, both of
+ which are ``INTEGER``\ s. Here is the ASN.1 type definition:
+
+ .. code::
+
+ RSAPublicKey ::= SEQUENCE {
+ modulus INTEGER, -- n
+ publicExponent INTEGER -- e }
+
+ The following sample code (error handling omitted for brevity) encodes a ``RSAPublicKey`` from
+ a modulus and a public exponent and imports the public key into NSS.
+
+ .. code::
+
+ struct MyRSAPublicKey {
+ SECItem m_modulus;
+ SECItem m_exponent;
+ } inPubKey;
+
+ SECItem derPubKey;
+
+ SECKEYPublicKey *pubKey;
+
+ const SEC_ASN1Template MyRSAPublicKeyTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(MyRSAPublicKey) },
+ { SEC_ASN1_INTEGER, offsetof(MyRSAPublicKey,m_modulus), },
+ { SEC_ASN1_INTEGER, offsetof(MyRSAPublicKey,m_exponent), },
+ { 0, }
+ };
+
+ PRArenaPool *arena;
+
+ /*
+ * Point inPubKey.m_modulus and m_exponent at the data, and
+ * then set their types to unsigned integers.
+ */
+ inPubKey.m_modulus.type = siUnsignedInteger;
+ inPubKey.m_exponent.type = siUnsignedInteger;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SEC_ASN1EncodeItem(arena, &derPubKey, &inPubKey,
+ MyRSAPublicKeyTemplate);
+ pubKey = SECKEY_ImportDERPublicKey(&derPubKey, CKK_RSA);
+ PORT_FreeArena(arena, PR_FALSE);
+
+ - Public keys may be extracted from certificates. Given a certficate (``CERTCertificate *``),
+ use ``CERT_ExtractPublicKey()`` to extract its public key. The returned public key may be used
+ after the certificate is destroyed.
+
+ When the keys are no longer needed, they need to be destroyed.
+
+ - Use ``SECKEY_DestroyPublicKey()`` to destroy a public key (``SECKEYPublicKey *``).
+ - Use ``SECKEY_DestroyPrivateKey()`` to destroy a private key (``SECKEYPrivateKey *``).
+ - Unlike ``SECKEYPublicKey`` and ``SECKEYPrivateKey``, ``PK11SymKey`` objects are reference
+ counted. Use ``PK11_ReferenceSymKey()`` to acquire a reference to a symmetric key
+ (``PK11SymKey *``). Use ``PK11_FreeSymKey()`` to release a reference to a symmetric key
+ (``PK11SymKey *``); the symmetric key is destroyed when its reference count becomes zero.
+
+`Functions <#functions>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ | RSA signing and encryption functions are provided by two layers of NSS function: the ``SGN_``
+ and ``VFY_`` functions in cryptohi.h, and the ``PK11_`` functions in pk11pub.h. As a general
+ principle, you should use the highest layer of NSS you can possibly use for what you are trying
+ to accomplish.
+ | For example, if you just need to generate or verify a signature, you can use the ``SGN_`` and
+ ``VFY_`` functions in cryptohi.h.
+ | If you need to interoperate with a protocol that isn't implemented by NSS, then you may need to
+ use the ``PK11_`` functions. (This API pretty much consists of what was needed to implement SSL
+ and S/MIME, plus a few enhancements over the years to support JSS.) When using the ``PK11_``
+ interfaces, the same principal applies: use the highest available function.
+ | If you are really trying to send a key, you should use ``PK11_PubWrapSymKey()``. For a low
+ level signature, use ``PK11_Sign()``. Both of these functions do the PKCS #1 wrapping of the
+ data. ``PK11_Sign`` does not do the BER encoding of the hash (as is done in ``SGN_``
+ functions).
+ | If you are trying to just send data, use ``PK11_PubEncryptPKCS1``.
+ | ``PK11_PubEncryptRaw`` is the lowest level function. It takes a modulus size data and does a
+ raw RSA operation on the data. It's used to support SSL2, which modifies the key encoding to
+ include the SSL version number.
+
+.. _pkcs_1_v1.5_block_formatting:
+
+`PKCS #1 v1.5 Block Formatting <#pkcs_1_v1.5_block_formatting>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ | Question:
+ | In PKCS #1 v1.5 (Section 8.1 Encryption-block formatting) and v2.1 (Section 7.2.1 Encryption
+ operation), PKCS1 v1.5 padding is described like this:
+ | ``00 || 02 || PS || 00 || M``
+ | but in PKCS #1 v2.0 (Section 9.1.2.1 Encoding operation, Step 3) and on the W3C web site
+ (http://www.w3.org/TR/xmlenc-core/#rsa-1_5), PKCS1 v1.5 padding is described like this:
+ | ``02 || PS || 00 || M``
+ | 00 at the beginning is missing. Why?
+ | Answer:
+ | The version without the initial 00 says :
+
+ .. container::
+
+ "PS is a string of strong pseudo-random octets [RANDOM] [...] long enough that the value of
+ the quantity being CRYPTed is one octet shorter than the RSA modulus"
+
+ |
+ | The version with the initial 00 instead says to pad to the same length as the RSA modulus.
+ | "The same length as the RSA modulus with an initial octet of 0" and "one octet shorter without
+ that initial octet" are exactly the same thing because the formatted block is treated as a
+ big-endian big integer by the RSA algorithm. The leading 00 octet is simply eight most
+ significant 0 bits. For example, 0x00123456 is equal to 0x123456.
+ | Perhaps this change made in PKCS #1 v2.0 confused many people, so it was reversed in v2.1.
+
+.. _sample_code:
+
+`Sample Code <#sample_code>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ - :ref:`mozilla_projects_nss_nss_sample_code_nss_sample_code_sample4`
+
+`References <#references>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ - `RSA Labs PKCS #1 web site <http://www.rsasecurity.com/rsalabs/node.asp?id=2125>`__
+ - `RFC 3447 <http://www.ietf.org/rfc/rfc3447.txt>`__: RSA PKCS #1 v2.1
+ - `Poupou's Blog: Common question: How to encrypt using
+ RSA <http://www.dotnet247.com/247reference/a.aspx?u=http://pages.infinit.net/ctech/20031101-0151.html>`__ \ No newline at end of file
diff --git a/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note8/index.rst b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note8/index.rst
new file mode 100644
index 0000000000..efbb737d82
--- /dev/null
+++ b/security/nss/doc/rst/legacy/nss_tech_notes/nss_tech_note8/index.rst
@@ -0,0 +1,130 @@
+.. _mozilla_projects_nss_nss_tech_notes_nss_tech_note8:
+
+nss tech note8
+==============
+
+.. _background_information_on_libssl's_cache_functions_and_sids:
+
+`Background Information on libSSL's Cache Functions and SIDs <#background_information_on_libssl's_cache_functions_and_sids>`__
+------------------------------------------------------------------------------------------------------------------------------
+
+.. container::
+
+.. _nss_technical_note_8:
+
+`NSS Technical Note: 8 <#nss_technical_note_8>`__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. container::
+
+ .. code::
+
+ 27 February 2006
+ Nelson B. Bolyard
+
+ Here is some background information on libSSL's cache functions and SIDs.
+
+ A SID (or sslSessionID struct) contains all the info needed to restart
+ the ssl session at a later time on another socket. The protocol code
+ builds such a structure, and then asks the cache code (client or server)
+ to save the info. The protocol code can also ask to remove a SID from
+ the cache.
+
+ Every SSL socket has two function pointers, ss->sec.cache and ss->sec.uncache,
+ which have the following types:
+ typedef void (*sslSessionIDCacheFunc) (sslSessionID *sid);
+ typedef void (*sslSessionIDUncacheFunc)(sslSessionID *sid);
+
+ There are two separate implementations of each function, one for clients
+ and one for servers. The client implementation caches or uncaches the
+ SID in the client session cache. The server implementation caches or
+ uncaches the SID in the server session cache.
+
+ For servers these pointers point to
+ sec->cache = ssl_sid_cache;
+ sec->uncache = ssl_sid_uncache;
+ which are functions defined in sslsnce.c, the server session cache source file.
+
+ For clients these pointers point to
+ sec->cache = CacheSID;
+ sec->uncache = LockAndUncacheSID;
+ which are functions defined in sslnonce.c, the client session cache source file.
+
+ The same cache/uncache API is used by both client and server code.
+ As originally designed, before calling the cache function, the caller was
+ responsible to fill in the session creation time (which might not be the
+ same as the time of insertion into the cache) and the session expiration
+ time, among other things.
+
+ Since NSS 1.0, up until NSS 3.4, there were two global variables that
+ contained the expected session lifetimes for ssl2 and ssl3 sessions.
+
+ extern PRUint32 ssl_sid_timeout; (the ssl2 session lifetime)
+ extern PRUint32 ssl3_sid_timeout; (the ssl3 session lifetime)
+
+ Each of these variables applied to both client and server sessions.
+ That is, the client session lifetime was NOT separately settable from the
+ server session lifetime.
+
+ These two variables were private, declared in a private header file.
+ There was no API function by which client programs could set these values.
+ However since NSS was delivered as archive libraries, client programs
+ merely declared these two variables for themselves, and then were able to
+ alter those variables directly.
+
+ For server programs, the function for initializing the server session cache
+ would set these two variables according to two of the arguments to that
+ function.
+
+ So, SSL protocol code that wanted to cache a SID would do these steps,
+ whether for client or for server:
+
+ For ssl2:
+ sid->lastAccessTime = sid->creationTime = ssl_Time();
+ sid->expirationTime = sid->creationTime + ssl_sid_timeout;
+ (*ss->sec.cache)(sid);
+ for ssl3:
+ sid->lastAccessTime = sid->creationTime = ssl_Time();
+ sid->expirationTime = sid->creationTime + ssl3_sid_timeout;
+ (*ss->sec.cache)(sid);
+
+ The cache API was defined such that the caller MUST set creationTime
+ properly, and may set expirationTime to the desired value or to zero.
+ If zero, then the called cache function would compute the correct
+ expiration time by adding the chosen timeout (from one of those two
+ global variables) to the SID's creationTime, giving the expirationTime.
+
+ However, none of the callers relied on the ability of the respective
+ cache functions to be able to compute the expiration time. All callers
+ computed the expiration times explicitly, as shown above.
+
+ The server side of the session cache code was largely rewritten for
+ NSS 3.4. The objectives were to make the server session cache faster,
+ and to fix bugs that caused corruption in multi-process servers, and also
+ to allow separate virtual servers to have their own session caches.
+
+ The new approach was to use shared memory for the server session cache,
+ and to allow multiple different server session caches to coexist.
+ As part of that work, I decided that each cache would have its own
+ variables containing the SSL2 and SSL3 session durations.
+ This means that client cache session lifetimes are separate from server
+ session cache lifetimes, and that each server session cache may have its
+ own lifetimes.
+
+ So, in NSS 3.4, the global variables ssl3_sid_timeout and ssl_sid_timeout
+ were intended to become the definitions for the client cache only, and
+ each server cache had its own new pair of variables for ssl2 and ssl3
+ session lifetimes, i.e., cache->ssl2Timeout and cache->ssl3Timeout.
+ The server cache initialization function was intended to no longer alter
+ the variables ssl3_sid_timeout and ssl_sid_timeout, but rather to set the
+ server cache's variables.
+
+ Since all the callers of the socket's cache function always initialized
+ both their creationTime and expirationTime using the client's session
+ lifetime variables, I changed the server's caching function to IGNORE the
+ expirationTime computed by the caller, and compute its own expiration
+ time, using the cache's own timeout values, or that was the intent.
+
+ But an implementation flaw caused the caching code to continue to use the
+ client's timeout time values, not the server cache's own timeout values.
+ That is the subject of bug 223242. \ No newline at end of file