Closed Bug 78959 Opened 23 years ago Closed 23 years ago

New NSS function returns SSL info not presently available

Categories

(NSS :: Libraries, enhancement, P1)

3.2.1
enhancement

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: nelson, Assigned: nelson)

References

Details

Attachments

(1 file)

Bug http://bugzilla.mozilla.org/show_bug.cgi?id=78837 requires
that NSS provide a way to access certain pieces of information
about an existing SSL connection so that PSM can display them.

The function presently available for this purpose, SSL_SecurityStatus() 
is documented at
http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslfnc.html#1092805
This function is inadequate in several respects, which I'll enumerate below.

Below that, I propose a new function to supersede SSL_SecurityStatus.  I want
to solicit your input on whether this new function adequately meets the 
needs.  This work is not yet part of any NSS PRD, and not scheduled for anyh

Inadequacies of SSL_SecurityStatus:

1. Does not indicate key exchange algorithm.
        RSA?  DHE?  Fortezza-KEA?

2. Does not indicate strength of key exchange key/value 
        512 bits?  1024 bits?  other?

3. Does not indicate server authentication algorithm.
        RSA?  DSA?

4. Does not indicate server authentication key size.
        512 bits?  1024 bits?  other?

5. Does not indicate SSL protocol version used.
        SSL 2?  SSL 3.0?  TLS (SSL 3.1)?

6. Does not indicate the digest algorithm used for message authentication
(MAC).  
        SHA1?  MD5?

6.1 Does not indicate the size of the digest used for MACs.  Presently, this
    value is implicitly determined from the particular MAC algorithm, but 
    in the future there will be "truncated MACs" which are shorter than 
    the full size given by the algorithm.

7. Returns a malloced ASCII string to identify the symmetric cipher used.
   
   - These strings are not localized (although it's not clear how to localize
     TLAs like RC2 and DES).  
   - The strings are inconsistent in identification of export status (key 
     strength).  For example, RC2-CBC with a 40 bit export key is identified
     as RC2-CBC-Export for SSL2 and as RC2-CBC-40 for SSL3.
   - Since the size of the key is available as an integer, there's really no 
     need to identify RC4 with a 40-bit key as a separate cipher from RC4 
     with a 128-bit key.  

8. Provides no information about whether client key exchange was done, and 
   what cert was used, or what key size or client authentication algorithm
   was used.  

9. Returns two values named "keySize" and "secretKeySize" whose meanings are 
   unclear to and often misinterpreted by programmers and users.

10. Returns RFC 1485 (ASCII-encoded) issuer and subject names for the peer's
    certificate (if any), but no other decoded info about the cert is made
    available.  However, the application can obtain the peer's cert and 
    extract what it needs with other libcert functions.

11. Returns an indicator of the "level" of security: Off, low, high, which 
    is based on outdated levels of expectation.  (56-bits is no longer 
    considered high security, for example.)  The application ought to make
    this value judgement for itself, IMO.

Before you read the proposed new function, please familiarize yourself with
the documentation on the existing function, at
http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslfnc.html#1092805

Proposed new function and structure.  

The newly proposed function returns all info in a caller-supplied structure.
The caller does not have to free any memory allocated by the function.
No strings are returned.  All values are numeric.  Translating the returned
numbers into strings is the responsibility of the calling application.

typedef enum {
    ssl_calg_null     = 0,
    ssl_calg_rc4      = 1,
    ssl_calg_rc2      = 2,
    ssl_calg_des      = 3,
    cssl_alg_3des     = 4,
    ssl_calg_idea     = 5,
    ssl_calg_fortezza = 6,      /* skipjack */
    ssl_calg_aes      = 7       /* coming soon */
} SSL3CipherAlgorithm;

typedef struct SSLChannelInfoStr {
        PRUint32             length;
        PRUint16             protocolVersion;     
        PRUint16             cipherSuite; 
        SSL3SignType         authAlgorithm;
        PRUint32             authKeyBits;
        SSLKEAType           keaType;
        PRUint32             keaKeyBits;
        SSL3CipherAlgorithm  bulkCipher;
        PRUint16             symKeyBits;
        PRUint16             symKeySpace;
        PRUint16             effectiveKeyBits;
        SSL3MACAlgorithm     macAlgorithm;
        PRUint16             macBits;
        PRUint8              reserved[64];
} SSLChannelInfo;

extern SECStatus SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info);

(I know that struct is not optimally packed, but at this point,
I want to discuss whether the requisite info is there, not how the struct
looks or struct member names. )

Notes:

- The structure has space reserved for future expansion.  Future versions
  of the structure will replace some of the reserved elements, but the 
  overall length will remain unchanged.  The length field at the beginning 
  indicates how much of the structure has been filled in by the present 
  version of NSS (not counting the unused reserved portion).

- All of these types (except SSL3CipherAlgorithm shown above) are presently
  defined in ssl header files, but some are defined in private header files,
  and will have to be moved to public header files.

- protocolVersion is the SSL protocol version.  Zero means SSL was not used.
  See SSL_LIBRARY_VERSION macros in sslproto.h for defined versions.

- cipherSuite values are defined in sslproto.h.  For SSL2, these are
  the SSL_EN_ symbols.  

- symKeyBits is the number of bits in the derived key for the symmetric 
  bulk encryption cipher. 

- symKeySpace is the logarithm (base 2) of the number of unique keys that
  can be derived for the symmetric cipher given the known values for the
  client and server "random" variables, and (for SSL2 only) the known bits
  for the master secret.  This number is not greater than symKeyBits.

- effectiveKeyBits is the logarithm (base 2) of the number of keys that
  must be tried (worst case) to find the symmetric cipher key, given the
  best available cryptanalysis of the cipher. This number is not greater
  than symKeySpace.

- macBits is the number of bits in the MAC in each SSL record, which may be
  less than or equal to the maximum number provided by the MAC algorithm.

- This struct does not contain any info about the peer's cert.  There is 
already a function for obtaining a reference to the peer's CERTCertificate
struct, and there are accessor functions that extract values (e.g. portions
of the name, validity dates, etc.) from that struct.  For example,
CERT_NameToASCII can be used to to extract the issuer name or subject name
from the certificate reference.

- This struct does not contain any info about the local cert (if any) that
was used to do client authentication.  However, since the application 
provides that cert to the SSL library through a callback function, the 
application ought to already have a pointer to that cert.  A function to 
return a reference to the local client cert could be added if needed.

An alternative proposal uses short arrays of char rather than integer 
values for the names of the algorithms.  This proposal asserts that
the names of the algorithms (e.g. "RSA", "DSA", "DES", "MD5", etc.) 
do not need localization.

typedef struct SSLChannelInfoStr {
        PRUint32             length;
        PRUint16             protocolVersion;     
        PRUint16             cipherSuite; 
        PRUint32             authKeyBits;
        PRUint32             keaKeyBits;
        PRUint16             symKeyBits;
        PRUint16             symKeySpace;
        PRUint16             effectiveKeyBits;
        PRUint16             macBits;
        char                 authAlgorithm[32];
        char                 keaType      [32];
        char                 bulkCipher   [32];
        char                 macAlgorithm [32];
        PRUint8              reserved     [64];
} SSLChannelInfo;


Comments on these proposals are invited.
I'm markign this assigned, but note that the target release for
this new feature has not yet been determined.
Blocks: 78837
Status: NEW → ASSIGNED
Blocks: 78894
In addition to the inadequacies mentioned in the initial statement of this bug,
the current API does not provide information about the FIPS status of the
connection.  The FIPS status needs to relect whether the TLS form of key
derivation was used together with a combination of FIPS approved encryption and
mac algorithms.
Target = NSS 3.4
Priority: -- → P2
Target Milestone: --- → 3.4
*** Bug 51440 has been marked as a duplicate of this bug. ***
This is checked in on the trunk.  

The test clients and server programs now use the new function instead
of the old, and report the information about the SSL connection.
It should be easy to modify the QA test scripts to verify that the 
reported information matches the expected information.
It may be necessary or desirable to modify the test clients/server to 
display this info on stdout instead of stderr, or vice versa.
Status: ASSIGNED → RESOLVED
Closed: 23 years ago
Resolution: --- → FIXED
Here are my comments on the SSLChannelInfo structure in
attachment 49707 [details].

1. The bitfield for isFIPS and reservedBits needs to be
   declared PRUint32 to ensure it has at least 32 bits.

2. I withdraw my suggestion for the flexibility to allow
   future expansion of the structure.  You can consider
   removing the length and reserved fields.

3. For each algorithm, why do you return both a string
   and an enum (for example, symCipherName and symCipher)?

Other than these, the structure looks good.
Jamie, please review the SSLChannelInfo structure and see
if it has all the information required by JSSE.
Here are three things that JSSE (the Java SSL API) provides that may be
difficult to implement with the existing NSS SSL API, and with the proposed
SSL_GetChannelInfo.

1. Cipher suite and protocol strings
SSLSession.getCipherSuite() returns the cipher suite as a string, apparently
using the names out of the specs. Examples are "SSL_RSA_WITH_RC4_128_MD5" and
"SSL_DH_anon_WITH_DES_CBC_SHA".

It also wants a string describing the protocol. For example, "SSLv3". I can
create a more exhaustive list of these strings if someone can tell me where I
can connect to SSLv2 and TLS servers.

2. Session Data
    - Creation Time: "the time at which this Session representation was created"
    - Last Accessed Time:
***BEGIN JAVADOC****
Returns the last time this Session representation was accessed by the session
level infrastructure, in milliseconds since midnight, January 1, 1970 UTC.

Access indicates a new connection being established using session data.
Application level operations, such as getting or setting a value associated with
the session, are not reflected in this access time.

This information is particularly useful in session management policies. For
example, a session manager thread could leave all sessions in a given context
which haven't been used in a long time; or, the sessions might be sorted
according to age to optimize some task.
****END JAVADOC****
    - ID: "the identifier assigned to this session". It is an array of 32 bytes.

3. Certificates
    - local certificates: the certificate(s) that were sent to the peer during
handshaking. Returns an ordered array of certificates, with the local
certificate first followed by any certificate authorities. This method allows
the caller to know which certificate chain was actually used.
    - peer certificates: an ordered array of peer X.509 certificates, with the
peer's own certificate first followed by any certificate authorities.
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
FYI, the javadoc for this stuff is at
http://java.sun.com/j2se/1.4/docs/api/javax/net/ssl/package-summary.html

SSLSession and SSLSocket are relevant.
Jamie, thanks for reviewing the SSL_GetChannelInfo()
API and noting the additional requirements from JSSE.

Nelson, I'd like to hear your opinion on Jamie's
comments.  My own comments below.

1. Cipher suite and protocol strings
It seems that the ciphersuite string that JSSE needs
can be constructed from the algorithm name strings
returned by SSL_GetChannelInfo().

2. Session Data
    - Creation Time
    - Last Accessed Time
    - ID
   If these session data should be returned by
   SSL_GetChannelInfo() but you don't have time
   to implement them, make sure that we have
   enough space for them in the 'reserved' array
   at the end of the SSLChannelInfo structure.
   (In fact, we could just add three new fields
   marked as reserved for these session data.)
   We can implement them in a future NSS release.

3. Certificates
    - local certificates
    - peer certificates
   It seems to me that these can be returned by a
   separate function.  If you think they should be
   returned by SSL_GetChannelInfo(), make sure that
   we have enough space for them in the 'reserved'
   array.
Status: REOPENED → ASSIGNED
Please evaluate the following alterative proposal for the implementation
of SSL_GetChannelInfo().  This proposal recognizes that most of the info
about the session is completely encoded in the cipher suite number, and
there is very little information about the SSL session that is not 
specified uniquely by the cipher suite number.  It also permits the 
application to inquire about the characteristics of a ciphersuite even
when no SSL session is in progress.

This proposal creates another new function: SSL_GetCipherSuiteInfo()
which takes a ciphersuite number and returns all the info about it.
I desire your feedback on this proposal.  

typedef struct SSLChannelInfoStr {
    PRUint32             length;
    PRUint16             protocolVersion;
    PRUint16             cipherSuite;

    /* server authentication info */
    PRUint32             authKeyBits;

    /* key exchange algorithm info */
    PRUint32             keaKeyBits;

    /* session info */
    PRUint32             creationTime;		/* seconds since Jan 1, 1970 */
    PRUint32             lastAccessTime;	/* seconds since Jan 1, 1970 */
    PRUint32             expirationTime;	/* seconds since Jan 1, 1970 */
    PRUint32             sessionIDLength;	/* up to 32 */
    PRUint8              sessionID    [32];
    PRUint8              reserved     [64];
} SSLChannelInfo;

SECStatus SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len);

typedef struct SSLCipherSuiteInfoStr {
    PRUint16             length;
    PRUint16             cipherSuite;

    /* Cipher Suite Name */
    const char *         cipherSuiteName;

    /* server authentication info */
    const char *         authAlgorithmName;
    SSLSignType          authAlgorithm;

    /* key exchange algorithm info */
    const char *         keaTypeName;
    SSLKEAType           keaType;

    /* symmetric encryption info */
    const char *         symCipherName;
    SSLCipherAlgorithm   symCipher;
    PRUint16             symKeyBits;
    PRUint16             symKeySpace;
    PRUint16             effectiveKeyBits;

    /* MAC info */
    const char *         macAlgorithmName;
    SSLMACAlgorithm      macAlgorithm;
    PRUint16             macBits;

    PRUintn              isFIPS       : 1;
    PRUintn              reservedBits :31;

    PRUint8              reserved     [64];
} SSLCipherSuiteInfo;

SECStatus SSL_GetCipherSuiteInfo(PRUint16 cipherSuite, 
                                 SSLCipherSuiteInfo *info, PRUintn len);

This last function can be used together with the list of implemented SSL
ciphersuites provided by libSSL (*) for the application to display or choose
from a list of ciphersuites that always matches the current libSSL.

(*) see http://lxr.mozilla.org/mozilla/source/security/nss/lib/ssl/ssl.h#58

I would also propose to reorder the list of implemented SSL ciphersuites to
be in descending order of desirability (strength).

This latest proposal provides all the info needed by SSLSession, except the
certificates. Will those be provided by some other function?
The API already contains functions to get the peer's cert, and to get the
chain for that (or any) cert.  I'm planning to change libssl so that it 
will hold onto the peer cert and its chain for the duration of the SSL
connection rather than only for the duration of processing the peer's
certificate message (as it does today).  This change  can be done in a 
way that is fully backwards compatible.

There is no function to get the "local" cert.  I'm thinking about that
issue.  The local application always tells libSSL which cert to send 
(for client auth), or the set of certs from which libssl should choose
one appropriate for the negotiated ciphersuite (for server auth), so 
one might argue that the application should already possess the "local"
cert without asking libssl.  But if libSSL can be made to easily answer
this question, then perhaps it should.  Stay tuned.
Priority: P2 → P1
I have just added the following new function to libSSL.
I'm going to assume that this meets the requirement unless someone
tells me otherwise.

/*
** Return a new reference to the certificate that was most recently sent
** to the peer on this SSL/TLS connection, or NULL if none has been sent.
*/
SSL_IMPORT CERTCertificate * SSL_LocalCertificate(PRFileDesc *fd);

Finally, note that the final version of the structures SSLChannelInfoStr
and SSLCipherSuiteInfoStr did not have the "reserved" byte arrays that
were proposed above.

I'm marking this bug fixed.  Please reopen it if you think it is not.
Status: ASSIGNED → RESOLVED
Closed: 23 years ago23 years ago
Resolution: --- → FIXED
Jamie told me that SSL_LocalCertificate must return the last cert 
previously sent on this SSL session, even if it was on a different
(e.g. earlier) connection.  So, I am reopening this, and must 
reimplement SSL_LocalCertificate.
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
I added a local Certificate value to the client session cache to make
SSL_LocalCertificate remember the client auth cert that we sent when
the SSL session was established accross later restarts of the session.
A similar effect on the server side was achieved without adding more
cert storage in the server cache.  

The strsclnt and selfserv programs may now be used to test the 
SSL_LocalCertificate function, as well as the other new functions
created for this enhancement request.  
Status: REOPENED → RESOLVED
Closed: 23 years ago23 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: