Template Version: @(#)sac_nextcase 1.68 02/23/09 SMI
This information is Copyright 2009 Sun Microsystems
1. Introduction
    1.1. Project/Component Working Name:
         OpenSSL RSA keys by reference in PKCS#11 keystores through the PKCS11 
engine
    1.2. Name of Document Author/Supplier:
         Author:  Jan Pechanec
    1.3  Date of This Document:
        13 October, 2009
    1.5. Email Aliases:
        1.5.1. Responsible Manager: Anup.Sekhar at Sun.COM
        1.5.2. Responsible Engineer: Jan.Pechanec at Sun.COM
        1.5.3. Marketing Manager: Mark.Thacker at Sun.COM
        1.5.4. Interest List: openssl-interest at Sun.COM

2. Project Summary
   2.1. Project Description:

        OpenSSL applications can not currently take advantage of the added
        security provided by hardware keystores/tokens. Changes are needed to
        allow OpenSSL applications to use PKCS#11 keystores provided via the
        Solaris Crypto Framework (softtoken, Sun Crypto Accelerator 6000, etc.)
        so that it's possible to access existing RSA private and public keys
        in the keystores through the OpenSSL API. Certificates cannot be used
        due to the limitations of the ENGINE API.

        The change needed is entirely within the PKCS#11 engine that has been
        internally developed at Sun. Presently the engine can load only RSA keys
        from files in PEM format stored on disk so no support for DSA keys will
        be added as part of this project. DSA keys in PKCS#11 keystores seem not
        be of the interest to our PKCS#11 engine users for now.

        Given the limitation of the existing OpenSSL ENGINE API we can only work
        with existing keys in the keystore. We will not be able to generate
        keys. For such operations, the PKCS#11 API or different tools such as
        pktool(1) must be used.

        While DSA keys support seems to be possible to add in the future, we
        would not be able to add support for referencing symmetric keys without
        extending the external ENGINE API.

        A potential use case might be mod_ssl in Apache, for example, or using
        OpenSSL scripts that implement basic certification authority together
        with SCA-6000 hardware keystore. Note that Apache's mod_ssl would need
        nontrivial changes to make use of RSA keys by reference and such changes
        are not part of this project.

   2.2. Risks and Assumptions:

        None.


3. Business Summary
   3.1. Problem Area:

        Users are more familiar with the OpenSSL API than the PKCS#11 API or NSS
        API, and more applications exist using the OpenSSL API than those using
        the latter ones. It's usually easier to modify an existing application
        that uses OpenSSL than to develop a new one, possibly using a different
        API. From those reasons, users are asking for a way to access RSA keys
        stored in PKCS#11 keystores through the OpenSSL API.

   3.3. Business Justification:

        People who buy SCA-6000 crypto cards very often want to use its HW
        keystore for RSA keys through OpenSSL API.

4. Technical Description:
    4.1. Details:

        4.1.1 Overview

        The OpenSSL ENGINE interface provides 2 functions for accessing private
        and public keys through an engine from any OpenSSL application:

                ENGINE_load_private_key(), ENGINE_load_public_key()

        the identification of the key is in the 1st parameter, "char *key_id",
        and it is up to the engine how to interpret it. Currently, the PKCS#11
        engine supports only RSA keys and "key_id" is interpreted as a filename.

        The present semantics of the "key_id" parameter will be extended 
        to accept a PKCS#11 URI. Such URI should uniquely identify the key
        in the PKCS#11 keystore. We will also start accepting "file://" URI to
        provide a workaround to solve possible clashes with the existing
        filenames starting with "pkcs11:" prefix. Note that "file://" URI will
        be only accepted when the engine is used.

        4.1.2 PKCS#11 URI

        The format of PKCS#11 URI was designed in Sun with possible future
        integration into the PKCS#11 standard in mind, and was discussed openly
        in the community mailing list. Its format follows. The ordering of
        attributes is NOT significant but every attribute can can be used at
        most once.

        pkcs11:[token=<label>][;manuf=<label>][;serial=<label>][;model=<label>]
               [;object=<label>][;objecttype=(public|private|cert)]
               [;passphrasedialog=(builtin|exec:<file>)]

        where:
                "token" is the token label, eg. "Sun Metaslot"

                "manuf" is the manufacturer ID, eg. "Sun Microsystems, Inc."

                "serial" is the serial number

                "model" is the model, eg. "sca6000"

                "object" is the object (key) label, eg. "mykey"

                "objecttype" is either "public", "private", or "cert"

                "passphrasedialog" was modeled after Apache's
                        SSLPassPhraseDialog directive. With "builtin", the
                        PKCS#11 engine uses getpassphrase(3c) to read the PIN
                        from the terminal. With "exec:<command>", the external
                        command is run and the PIN is read from its standard
                        output. Maximum PIN length supported is 256 bytes which
                        is the maximum that getpassphrase(3C) supports.

        Currently, the PKCS#11 engine ignores the "objecttype" keyword since by
        using the specific load function it is determined what key type will be
        searched for. "objecttype" is specified here for the sake of
        completeness of the PKCS#11 URI specification. Also note that we cannot
        work with certificates that way, only with public and private keys.

        The keyword "pin" is intentionally NOT provided due to inherent security
        problems of using a piece of secret information in the process arguments
        that are visible in the process list to all users of the system.

        If "passphrasedialog" is not provided but ENGINE_load_private_key() is
        used and the token requires PIN the ENGINE_load_private_key() function
        will fail. The same is true for cases where token is not initialized or
        PIN is not set (but required). However, if PIN is not required by the
        token the engine will continue. That's the case when public keys are
        referenced.

        The only mandatory attribute is the "object" attribute that contains the
        key label. As noted below, the engine's use of the slots automatically
        determines the keystore used which might seem to obsolesce the use of
        token attributes "token", "manuf", "serial", and "model". However, users
        might want to provide such information to make sure they pick the right
        keystore. If the provided information does NOT match with the keystore
        used by the slot chosen in the engine, the load operation will fail.

        4.1.3 Technical Details

        The PKCS#11 engine never reads private components of the keys stored in
        the keystores to the memory, no matter whether those keys are labeled
        sensitive or not. Both ENGINE_load_private_key() and
        ENGINE_load_public_key() return a native OpenSSL structure called
        EVP_PKEY. Even for the private key, the structure will contain only
        public components of the key and those components will be used to look
        up the PKCS#11 object handle for the private key for every operation
        performed on that key.

        If an application is using the key by reference approach it must NOT
        expect to be able to use private key components internally. If the
        application uses the OpenSSL API properly, private key components in the
        process memory would be needed only for exporting the private key from
        the keystore but never for signing.

        4.1.3 Sun's PKCS#11 engine specifics

        Currently, the PKCS#11 engine uses the same slot for all RSA/DH/DSA
        operations and the slot is chosen during the initialization of the
        engine. That means that we can use only the keystore that the chosen 
slot
        provides. Usually that will be "Sun Metaslot" because the PKCS#11 engine
        will use that slot unless manually disabled. Note that by default, the
        softtoken keystore is used as the metaslot's token. Users can use
        metaslot's METASLOT_OBJECTSTORE_TOKEN environment variable to switch to
        a different, possibly hardware, keystore. More specifically, if the URI
        specifies a different token name in its "token" attribute
        than the one used by the metaslot, the engine will fail when trying to
        load the key. That way the user can use those attributes to make sure
        the correct key is used. The same stands for "manuf", "serial", and
        "model" attributes. For more information on the metaslot's keystore, see
        libpkcs11(3LIB).

        If more than one key with a given specification is found the engine will
        fail in its load functions.

        Given the known issues with the PKCS#11 fork safety requirements the
        engine tries to re-initialize itself in the child when the fork is
        detected. When the parent is logged into the token, the child must log
        in again in order to continue to access private keys loaded in the
        parent. A built-in passphrase dialog will not be probably suitable for
        re-reading the PIN from the child. See the "4.1.4 PIN Caching Policy"
        for how to cache the PIN in memory. Alternatively, use
        "passphrasedialog" with the "exec" option. Failure to provide a PIN in
        the child is a failure to continue to use the engine. It's up to the
        user to adequately secure the external command if used.

        4.1.4 PIN Caching Policy

        The PKCS#11 engine does NOT cache the PIN in memory by default. We
        assume that if the application does not fork then caching the PIN by
        default would not be only useless but also potentially dangerous (PIN
        could end up in swap or system and process core dumps). However, we
        provide 2 options for PIN caching so that the PIN can be used in the
        child to relogin to the token. The engine honors a special environment
        variable:

        OPENSSL_PKCS11_PIN_CACHING_POLICY

        which can have "none", "mlocked-memory", and "memory" values.

        The "none" value is the default where the PIN is forgotten after the
        login. "memory" will keep the PIN in the memory, and "mlocked-memory"
        will keep the PIN in a locked page via mlock(3C). Note that mlock()
        requires the PRIV_PROC_LOCK_MEMORY privilege which is not in the default
        user set. An admin must grant the application or the user the relevant
        privilege if the "mlocked-memory" option is to be used. With that option
        and without the privilege the load function will fail on loading the 1st
        private key if the token requires the PIN - it will NOT resort to use
        the "memory" option. Also, if the PIN is required then any incorrect
        value of OPENSSL_PKCS11_PIN_CACHING_POLICY will result in a failure in
        the load function. If the PIN is not required (eg. providing a PIN in
        URIs for public keys only) the PIN will not be used and will be erased
        from memory no matter how OPENSSL_PKCS11_PIN_CACHING_POLICY is set.

        While we could use the ENGINE control API to provide such information to
        the engine the use of an enviroment variable seems to be more apropriate
        here since it will provide more options to applications using RSA keys
        by reference without any need for code modifications.

        4.1.5 Accessing DSA keys

        Currently, the engine does not provide for loading DSA keys from the
        disk through the engine. While this could be done and DSA keys could be
        used from the HW key stores it is not part of the project. What's more,
        we haven't received any user requests to provide such functionality yet.


    4.2. Bug/RFE Number(s):

        the project implements this RFE:

                6479874 OpenSSL should support RSA key by reference/hardware
                        keystores

        I'll fix following PKCS#11 engine CRs as part of this project:

                6732677 make check to trigger Solaris specific code automatic in
                        the PKCS#11 engine
                6872415 pkcs11 engine's check_new_rsa_key_priv() should use a
                        public key component

    4.5. Interfaces:

        - we do NOT add any new command line option or OpenSSL API functions

        - we overload the filename options so that PKCS#11 URI can be provided,
          see above.

        
    4.6. Doc Impact:

        Manual page for openssl(5) will be modified. Draft follows.


--- openssl.5   Wed Aug 19 16:04:12 2009
+++ openssl.5.new       Wed Sep 30 12:39:57 2009
@@ -36,40 +36,116 @@
      to the Cryptographic Framework through the PKCS#11 engine on
      a given machine, run the following command:
 
        /usr/sfw/bin/openssl engine -vvv -t -c
 
      Due  to  requirements  of  the  PKCS#11  standard  regarding
      fork(2) behavior, some applications that use the OpenSSL EVP
      interfaces and fork()  with  active  crypto  contexts  might
      experience unexpected behavior.
 
+  Building an OpenSSL Application
+
      To build an OpenSSL application, use the following  cc  com-
      mand line options:
 
        cc [ flag... ] file... -lcrypto -lssl [ library... ]
 
+  Accessing RSA Keys in PKCS#11 Keystores
+
+     OpenSSL can access RSA keys in PKCS#11 keystores using the
+     following functions of the ENGINE API:
+
+       EVP_PKEY *ENGINE_load_private_key(ENGINE *e,
+                       const char *key_id, UI_METHOD *ui_method,
+               void *callback_data)
+
+       EVP_PKEY *ENGINE_load_public_key(ENGINE *e,
+                       const char *key_id, UI_METHOD *ui_method,
+               void *callback_data)
+
+     key_id, formerly for filenames only, can be now also set to
+     a PKCS#11 URI. To avoid clashes with existing filenames,
+     "file://" prefix for filenames is now also accepted but
+     only when the PKCS#11 engine is in use. The PKCS#11 URI
+     specification follows:
+
+       pkcs11:[token=<label>][;manuf=<label>][;serial=<label>]
+              [;model=<label>][;object=<label>]
+              [;objecttype=(public|private|cert)]
+              [;passphrasedialog=(builtin|exec:<file>)]
+
+     The ordering of keywords is not significant. The PKCS#11
+     engine uses the keystore for the slot chosen for public key
+     operations whic is metaslot on a standardly configured
+     machine. Currently, the PKCS#11 engine ignores "objecttype"
+     keyword. The only mandatory keyword is "object" which is
+     the key object label. For information on how to use a
+     different, possibly hardware, keystore with metaslot see
+     libpkcs11(3LIB).
+
+     The token PIN is provided via "passphrasedialog" keyword and
+     is either read from the terminal ("builtin") or from the
+     output of an external command ("exec:<file>"). The PIN is
+     used to log into the token and by default is deleted from
+     the memory then. The keyword "pin" is intentionally not
+     provided due to inherent security problems of possible use
+     of a password in the process arguments.
+
+     Due to fork safety issues the application must re-login if
+     the child continues to use the PKCS#11 engine. It is done
+     inside of the engine automatically if fork is detected and
+     in that case, "exec:<file>" option of the "passphrasedialog"
+     keyword can be used. Alternatively, an enviroment variable
+     OPENSSL_PKCS11_PIN_CACHING_POLICY can be used to allow the
+     PIN to be cached in memory and reused in the child. It can
+     be set to "none" which is the default, "memory" to store
+     the PIN in memory, and "mlocked-memory" keep the PIN in a
+     locked page via mlock(3C). Note that PRIV_PROC_LOCK_MEMORY
+     privilege is required in that case.
+
+     Sensitive parts of private keys are never read from the
+     token to the process memory no matter whether the key is
+     tagged with sensitive flag or not. The PKCS#11 engine uses
+     the public compoments as a search key to get a PKCS#11
+     object handle to the private key.
+
+  Additional Documentation
+
      Extensive additional documentation for  OpenSSL  modules  is
      available       in      the      /usr/share/man/man1openssl,
      /usr/share/man/man3openssl, /usr/share/man/man5openssl,  and
      /usr/share/man/man7openssl directories.
 
      To view the license terms, attribution,  and  copyright  for
      OpenSSL, see /var/sadm/pkg/SUNWopensslr/install/copyright.
 
+EXAMPLES
+
+     Example 1: generate and print a public key stored in an
+               already initilized PKCS#11 keystore. Note the
+               use of "-engine pkcs11" and "-inform e".
+
+       $ pktool gencert keystore=pkcs11 label=mykey \
+           subject="CN=test" keytype=rsa keylen=1024 serial=01
+       $ openssl rsa -in "pkcs11:object=mykey;passphrasedialog=builtin" \
+           -pubout -text -engine pkcs11 -inform e
+
 ATTRIBUTES
      See attributes(5) for a description of the following  attri-
      butes:
 
      ____________________________________________________________
     |       ATTRIBUTE TYPE        |       ATTRIBUTE VALUE       |
     |_____________________________|_____________________________|
     | Availability                | SUNWopensslr, SUNWopenssl   |
     |_____________________________|_____________________________|
     | Interface Stability         | External                    |
     |_____________________________|_____________________________|
 
 SEE ALSO
-     cryptoadm(1M), libpkcs11(3LIB), attributes(5)
+     cryptoadm(1M), libpkcs11(3LIB), attributes(5),
+     privileges(5), mlock(3C)
 
      /usr/share/man/man1openssl/openssl.1openssl,
-     /usr/sfw/man/man3/engine.3, /usr/sfw/man/man3/evp.3
+     /usr/share/man/man3openssl/engine.3,
+     /usr/share/man/man3openssl/evp.3


6. Resources and Schedule
    6.4. Steering Committee requested information
        6.4.1. Consolidation C-team Name:
                SFW
    6.5. ARC review type: FastTrack
    6.6. ARC Exposure: open

Reply via email to