Thursday Mar 31, 2011

SNI and bench marking tools - ab and siege

SNI and bench marking tools - ab and siege

I wanted to do some performance measurements on some SNI server using some too. I evaluated two tools.

1. "ab" (Apache HTTP server benchmarking tool)

So I have to build "ab" so that it takes HTTPS URL and not just HTTP URL and sends TLS SNI extension in SSL handshake.

1.1. Download OpenSSL and Apache source code

I downloaded OpenSSL source code (openssl-1.0.0d.tar) from http://www.openssl.org/source/ and Apache source code from http://httpd.apache.org/ (httpd-2.3.11-beta.tar and httpd-2.3.11-beta-deps.tar).

But I had to make the following two changes in Apache code.

1.2. Modify configure.in

$diff configure.in configure.in.ORIGINAL
611,614d610
< if test "$enable_ssl" != "no"; then
<   APR_ADDTO(DEFS, "-DAB_USE_SSL")
< fi
<

I took these changes from http://www.mail-archive.com/dev@httpd.apache.org/msg25661.html

1.3. Modify support/ab.c

First I tried  calling the function SSL_set_tlsext_host_name(c->ssl, host_field); but it gave undefined symbol error, so I used SSL_ctrl function instead.

$diff ab.c ab.c.orig
184d183
< #include <openssl/tls1.h> /\* for TLSEXT_NAMETYPE_host_name \*/
1182d1180
<
1244,1245d1241
<         SSL_ctrl(c->ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, host_field);
< 

1.4. Building and Installing OpenSSL and Apache

I built and installed OpenSSL and Apache as given in

http://www.linuxquestions.org/questions/linux-server-73/openssl-support-for-sni-and-tls-799387/#10


OpenSSL :

$./config --prefix=/usr/local --openssldir=/usr/local/openssl enable-tlsext shared
$make && make install


Apache :

$LDFLAGS=-L/usr/local/lib CPPFLAGS=-I/usr/local/include/ ./configure --enable-so --enable-ssl --enable-rewrite --enable-unique-id --with-ssl=/usr/local/
$make && make install

1.5. Send a test request using "ab" and confirm using ssltap

Set LD_LIBRARY_PATH to the OpenSSL directory (containing libssl.so) :

    $export LD_LIBRARY_PATH=/usr/local/lib/:$LD_LIBRARY_PATH

Confirm that ab -help shows "http[s]" in the usage as shown below :

   $/usr/local/apache2/bin/ab -help

   Usage: ./ab [options] [http[s]://]hostname[:port]/path

Now send a single request and route it to the server using ssltap to confirm if "ab" is working fine :

$./ab -n 1 -c 1 -f TLS1 https://www.foo.com:1924/abc.html

ssltap output shows that the server name "www.foo.com"  was sent in SSL Handshake :


$ssltap -s -l -p 1924 foo.com:port

--> [
  (230 bytes of 225)
  SSLRecord { [Thu Mar 31 19:43:21 2011]
     type    = 22 (handshake)
     version = { 3,1 }
     length  = 225 (0xe1)
     handshake {
        type = 1 (client_hello)
        length = 221 (0x0000dd)
           ClientHelloV3 {
              client_version = {3, 1}
              random = {...}
              session ID = {
                  length = 0
                  contents = {...}
              }
              cipher_suites[46] = {

...             } ...             extensions[88] = {

 extension type server_name, length [16] = {

  0: 00 0e 00 00  ... 2e 63 6f 6d  | .....www.foo.com } ...


2. siege

Downloaded  siege-2.70.tar.gz from ftp://ftp.joedog.org/pub/siege/siege-2.70.tar.gz

$gunzip siege.tar.gz

$tar -xvf siege.tar

$cd siege-2.70

Make these code changes

$diff client.c client.c.orig
292c292
<     if (SSL_initialize(C, U->hostname)==FALSE) {
---
>     if (SSL_initialize(C)==FALSE) {

$diff ssl.h ssl.h.orig
52c52
< BOOLEAN SSL_initialize(CONN \*C, const char \*servername);
---
> BOOLEAN SSL_initialize(CONN \*C);

$diff ssl.c ssl.c.orig
43d42
< #include <tls1.h>
67c66
< SSL_initialize(CONN \*C, const char \*servername)
---
> SSL_initialize(CONN \*C)
137,138d135
<   SSL_ctrl(C->ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME,
<            TLSEXT_NAMETYPE_host_name, servername);

Build and install siege :

$./configure --with-ssl=/usr/local/


$make

$make install

$export LD_LIBRARY_PATH=/usr/local/lib/:$LD_LIBRARY_PATH

Run siege

$/usr/local/bin/siege -c 10 -t1M https://www.foo.com:3333/index.html

you can confirm that siege sent SNI TLS extension using ssltap.

3. References

Monday Feb 28, 2011

What's New in NSS 3.12.6 - SSL3 & TLS Renegotiation Indication Extension - NSS flags NSS_REQUIRE_SAFE_RENEGOTIATION and NSS_SSL_ENABLE_RENEGOTIATION

What's New in NSS 3.12.6 - SSL3 & TLS Renegotiation Indication Extension - NSS flags NSS_REQUIRE_SAFE_RENEGOTIATION and NSS_SSL_ENABLE_RENEGOTIATION

I tried my hands on various TLS renegotiation scenarios by setting these two flags NSS_REQUIRE_SAFE_RENEGOTIATION and NSS_SSL_ENABLE_RENEGOTIATION using sample SSL Server built with NSS 3.12.6 (and test case requires renegotiation).

As per NSS 3.12.6 release notes for NSS 3.12.6 (or above) the default values are

  • NSS_SSL_ENABLE_RENEGOTIATION = SSL_RENEGOTIATE_REQUIRES_XTN and
  • NSS_SSL_REQUIRE_SAFE_NEGOTIATION = PR_FALSE.

Sent requests using test tool tstclnt of NSS 3.12.6, NSS 3.12.4 and 3.12.5 with these flags set in server :

Note that in NSS 3.12.5 (in this renegotiation is disabled) so re-negotiations fail in all cases as expected.


Server has flag
NSS_SSL_ENABLE_RENEGOTIATION =

Server has flag NSS_REQUIRE_SAFE_RENEGOTIATION
=

Controls whether safe renegotiation indication is required for initial handshake. If TRUE, a connection will be dropped at initial handshake if the peer server or client does not support safe renegotiation.

Client version NSS 3.12.6 or above - client supports safe renegotiation
client version NSS 3.12.4 - older clients - client doesn't support safe renegotiation
client version NSS 3.12.5 - renegotiation disabled - client doesn't support safe renegotiation

SSL_RENEGOTIATE_NEVER (0)
Never allow renegotiation
TRUE
FAILURE - SSL_ERROR_RENEGOTIATION_NOT_ALLOWED FAILURE - SSL_ERROR_HANDSHAKE_NOT_COMPLETED FAILURE - SSL_ERROR_HANDSHAKE_NOT_COMPLETED
FALSE
FAILURE - SSL_ERROR_RENEGOTIATION_NOT_ALLOWED  FAILURE - SSL_ERROR_RENEGOTIATION_NOT_ALLOWED FAILURE - SSL_ERROR_RENEGOTIATION_NOT_ALLOWED
SSL_RENEGOTIATE_UNRESTRICTED (1)

Server and client are allowed to renegotiate without any restrictions.
TRUE
SUCCESS FAILURE - SSL_ERROR_HANDSHAKE_NOT_COMPLETED FAILURE - SSL_ERROR_HANDSHAKE_NOT_COMPLETED
FALSE
SUCCESS SUCCESS FAILURE -
PR_END_OF_FILE
SSL_RENEGOTIATE_REQUIRES_XTN (2)
(Default in NSS 3.12.6 or above)
Only allows renegotiation if the peer's hello bears the TLS renegotiation_info extension. This is the safe renegotiation.
TRUE
SUCCESS FAILURE -
SSL_ERROR_HANDSHAKE_NOT_COMPLETED
FAILURE - SSL_ERROR_HANDSHAKE_NOT_COMPLETED
FALSE
(Default in NSS 3.12.6 or above)
SUCCESS FAILURE - SSL_ERROR_RENEGOTIATION_NOT_ALLOWED FAILURE -
PR_END_OF_FILE

SSL_RENEGOTIATE_TRANSITIONAL (3)

Disallows unsafe renegotiation in server sockets only, but allows clients to continue to renegotiate with vulnerable servers.

TRUE
SUCCESS FAILURE - SSL_ERROR_HANDSHAKE_NOT_COMPLETED FAILURE - SSL_ERROR_HANDSHAKE_NOT_COMPLETED
FALSE
SUCCESS FAILURE - SSL_ERROR_RENEGOTIATION_NOT_ALLOWED FAILURE -
PR_END_OF_FILE



What these error codes mean

Error Error Number Error Text
SSL_ERROR_RENEGOTIATION_NOT_ALLOWED -12176 "Renegotiation is not allowed on this SSL socket."
SSL_ERROR_HANDSHAKE_NOT_COMPLETED -12202 "Cannot initiate another SSL handshake until current handshake is complete."
PR_END_OF_FILE_ERROR -5938 "Encountered end of file"

Here is my Server program

Here is my Makefile :

all:
 rm -rf server server.o
 CC -o server -I/export1/NSS_3.12.6/SunOS5.10_OPT.OBJ/include -L/export1/NSS_3.12.6/SunOS5.10_OPT.OBJ/lib -lnspr4 -lplc4 -lplds4 -lnss3 -lssl3 server.cpp

Created Server certificate using certutil as shown below:

$certutil -N -d . 
$certutil -S -n Server-Cert -s "CN=test.com" -x -t "CT,CT,CT" -d .

I sent request using sslreq.txt

GET /test.html HTTP/1.0
end

Here are the sample client and server Error logs , ssltap output in these 4 distinctive results


References

Monday Jan 17, 2011

What's new in NSS 3.12.\* - Server Name Indication (SNI) callback

What's new in NSS 3.12.\* - Server Name Indication (SNI) callback

When a request comes in to a web server, it sends the domain name in the Host header.

"GET /test.html HTTP/1.0

Host: abc.com"

by the time any web server parses it, its too late to send the appropriate certificate as it was already sent in the SSL Handshake. As per RFC4366, we now have a new extension in Handshake with which client can tell server the required domain. So the server can send appropriate certificate in the handshake.

In a Web Server, we can configure only one certificate of a type (ECC/RSA etc.) per HTTP listener using SSL_ConfigureSecureServer(fd...) call. If the server has to be used for one more domain, we need to regenerate the certificate with that domain in Subject Alternate Names. But with Server Name Indication (SNI) extension, we can register, more than one certificates (of a particular type) per HTTP listener.

In NSS 3.12.6 a new SNI callback was added as a part of bug 360421. Any Server which uses NSS can set this callback function (similar to what is shown in selfserv.c#1709) and write its implementation to send appropriate SNI certificate at runtime.

I used two binaries bundled with NSS selfserv and tstclnt to see what is happening. (I have used NSS 3.12.8)

Create two server certificates "www.foo.com" and "www.bar.com"

$certutil -N -d .
$certutil -S -x -n www.foo.com -s "CN=www.foo.com" -t CTu,u,u -d .
$certutil -S -x -n www.bar.com -s "CN=www.bar.com" -t CTu,u,u -d .

start the server

$selfserv -D -B -s -p 4443  -n www.foo.com  -r -a www.bar.com -d .

Where
-D => disable Nagle delays in TCP
-B => bypasses the PKCS11 layer
-s => disable SSL socket locking
-n  rsa_cert_nickname
-a is used to configure server for SNI. [-a sni_cert_nickname]
-r => request, not require, cert on initial handshake.

create sslreq.cat

$cat > req.dat  
GET /test.html HTTP/1.0

 


Now send a request asking for domain "www.bar.com"

$tstclnt -p 4443 -h www.foo.com -f -d  . -n www.foo.com  -2 -a www.bar.com  < sslreq.dat

where
-n => Nickname of key & cert for client auth (use www.foo.com  for now)
-a => Send different SNI name. [-a 1st_handshake_sni_cert_name]

We get : 

subject DN: CN=www.bar.com
issuer  DN: CN=www.bar.com
0 cache hits; 1 cache misses, 0 cache not reusable
0 stateless resumes
HTTP/1.0 200 OK
Server: Generic Web Server
Date: Tue, 26 Aug 1997 22:10:05 GMT
Content-type: text/plain
GET /test.html HTTP/1.0
EOF

As you can see, the server returned the certificate for "www.bar.com"

To know what's happening look at the ssltap output (use -c z in selfserv and tstclnt both):

$ssltap -l -s -p 1925 foo:4443
Connection #1 [Mon Jan 17 14:51:12 2011]
Connected to foo:4443
--> [
(74 bytes of 69)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 69 (0x45)
   handshake {
      type = 1 (client_hello)
      length = 65 (0x000041)
         ClientHelloV3 {
            client_version = {3, 1}
            random = {...}
            session ID = {
                length = 0
                contents = {...}
            }
            cipher_suites[2] = {
                (0x00ff) ????/????????/?????????/???
                (0x0002) SSL3/RSA/NULL/SHA
            }
            compression[1] = {
                (00) NULL
            }
  extensions[20] = {
  extension type server_name, length [16] = {
   0: 00 0e 00 00  0b 77 77 77  2e 62 61 72  2e 63 6f 6d  | .....www.bar.com
              }
            }
         }
   }
}
]
<-- [
(590 bytes of 585)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 585 (0x249)
   handshake {
      type = 2 (server_hello)
      length = 81 (0x000051)
         ServerHello {
            server_version = {3, 1}
            random = {...}
            session ID = {
                length = 32
                contents = {...}
            }
            cipher_suite = (0x0002) SSL3/RSA/NULL/SHA
            compression method = (00) NULL
            extensions[9] = {
              extension type 65281, length [1] = {
   0: 00                    | .
              }
              extension type server_name, length [0]
            }
         }
      type = 11 (certificate)
      length = 430 (0x0001ae)
         CertificateChain {
            chainlength = 427 (0x01ab)
            Certificate {
               size = 424 (0x01a8)
               data = { saved in file 'cert.001' }
            }
         }
      type = 13 (certificate_request)
      length = 58 (0x00003a)
         CertificateRequest {
            certificate types[3] = { 01 02 40 }
            certificate_authorities[52] = {
CN=www.bar.com
   CN=www.foo.com
            }
         }
      type = 14 (server_hello_done)
      length = 0 (0x000000)
   }
}
]
--> [
(754 bytes of 702, with 47 left over)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 702 (0x2be)
   handshake {
      type = 11 (certificate)
      length = 430 (0x0001ae)
         CertificateChain {
            chainlength = 427 (0x01ab)
            Certificate {
               size = 424 (0x01a8)
               data = { saved in file 'cert.002' }
            }
         }
      type = 16 (client_key_exchange)
      length = 130 (0x000082)
         ClientKeyExchange {
            message = {...}
         }
      type = 15 (certificate_verify)
      length = 130 (0x000082)
   }
}
(754 bytes of 1, with 41 left over)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 20 (change_cipher_spec)
   version = { 3,1 }
   length  = 1 (0x1)
}
(754 bytes of 36)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 36 (0x24)
   handshake {
      type = 20 (finished)
      length = 12 (0x00000c)
         Finished {
            verify_data = {...}
         }
   }
      MAC = {...}
}
]
<-- [
(47 bytes of 1, with 41 left over)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 20 (change_cipher_spec)
   version = { 3,1 }
   length  = 1 (0x1)
}
(47 bytes of 36)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 36 (0x24)
   handshake {
      type = 20 (finished)
      length = 12 (0x00000c)
         Finished {
            verify_data = {...}
         }
   }
      MAC = {...}
}
]
--> [
(50 bytes of 45)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 23 (application_data)
   version = { 3,1 }
   length  = 45 (0x2d)
   0: 47 45 54 20  2f 74 65 73  74 2e 68 74  6d 6c 20 48  | GET /test.html H
  10: 54 54 50 2f  31 2e 30 0a  0a                        | TTP/1.0..
      MAC = {...}
}
]
<-- [
(196 bytes of 164, with 27 left over)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 23 (application_data)
   version = { 3,1 }
   length  = 164 (0xa4)
   0: 48 54 54 50  2f 31 2e 30  20 32 30 30  20 4f 4b 0d  | HTTP/1.0 200 OK.
  10: 0a 53 65 72  76 65 72 3a  20 47 65 6e  65 72 69 63  | .Server: Generic
  20: 20 57 65 62  20 53 65 72  76 65 72 0d  0a 44 61 74  |  Web Server..Dat
  30: 65 3a 20 54  75 65 2c 20  32 36 20 41  75 67 20 31  | e: Tue, 26 Aug 1
  40: 39 39 37 20  32 32 3a 31  30 3a 30 35  20 47 4d 54  | 997 22:10:05 GMT
  50: 0d 0a 43 6f  6e 74 65 6e  74 2d 74 79  70 65 3a 20  | ..Content-type:
  60: 74 65 78 74  2f 70 6c 61  69 6e 0d 0a  0d 0a 47 45  | text/plain....GE
  70: 54 20 2f 74  65 73 74 2e  68 74 6d 6c  20 48 54 54  | T /test.html HTT
  80: 50 2f 31 2e  30 0a 0a 45  4f 46 0d 0a  0d 0a 0d 0a  | P/1.0..EOF......
      MAC = {...}
}
(196 bytes of 22)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 21 (alert)
   version = { 3,1 }
   length  = 22 (0x16)
   warning: close_notify
      MAC = {...}
}
]

 Note that the client sent "www.bar.com" to the server in the extension.

Also that server sends the certificate (cert.001) i.e. "www.bar.com"  to the client.  

$openssl x509  -in cert.001 -text -inform DER

Certificate:

    Data:

        Version: 3 (0x2)

        Issuer: CN=www.bar.com

        Subject: CN=www.bar.com

And the client sends the certificate (cert.002) i.e. "www.foo.com"  to the server.

$openssl x509  -in cert.002 -text -inform DER

Certificate:

    Data:

        Version: 3 (0x2)

        Issuer: CN=www.foo.com

        Subject: CN=www.foo.com

Now send a request asking for domain "www.domain-not-found.com", the server is unable to find a certificate registered for such a domain and hence returns error. This behavior will vary from server to server depending on the implementation. 

$tstclnt -p 4443 -h www.foo.com -f -d  . -n www.foo.com  -2 -a "www.domain-not-found.com"  < sslreq.dat

 We get the error :

 tstclnt: write to SSL socket failed: SSL peer has no certificate for the requested DNS name

For this case, ssltap output shows an "unrecognize_name" alert (use -c z in selfserv and tstclnt):

$ssltap -l -s -p 1925 foo:4443
Connection #1 [Mon Jan 17 14:49:28 2011]
Connected to foo:4443
--> [
(87 bytes of 82)
SSLRecord { [Mon Jan 17 14:49:28 2011]
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 82 (0x52)
   handshake {
      type = 1 (client_hello)
      length = 78 (0x00004e)
         ClientHelloV3 {
            client_version = {3, 1}
            random = {...}
            session ID = {
                length = 0
                contents = {...}
            }
            cipher_suites[2] = {
                (0x00ff) ????/????????/?????????/???
                (0x0002) SSL3/RSA/NULL/SHA
            }
            compression[1] = {
                (00) NULL
            }
            extensions[33] = {
              extension type server_name, length [29] = {
  0: 00 1b 00 00  18 77 77 77  2e 64 6f 6d  61 69 6e 2d| .....www.domain-
 10: 6e 6f 74 2d  66 6f 75 6e  64 2e 63 6f  6d  | not-found.com
              }
            }
         }
   }
}
]
<-- [
(7 bytes of 2)
SSLRecord { [Mon Jan 17 14:49:28 2011]
   type    = 21 (alert)
   version = { 3,1 }
   length  = 2 (0x2)
   fatal: unrecognized_name
}
]
 
  

Looks like j2SE SNI client side support was integrated in J2SE 7 b118 CR6985179 To support Server Name Indication extension for JSSE client.

 Browsers that support TLS SNI

Refer http://en.wikipedia.org/wiki/Server_Name_Indication#Support for a full list. Some of these browsers are :

  • Internet Explorer 7 or later, on Windows Vista or higher. Does not work on Windows XP, even Internet Explorer 8.
  • Mozilla Firefox 2.0 or later
  • Google Chrome (Vista or higher. XP on Chrome 6 or newer. OS X 10.5.7 or higher on Chrome 5.0.342.1 or newer)
  • Safari 2.1 or later (Mac OS X 10.5.6 or higher and Windows Vista or higher)

References

Wednesday Jan 05, 2011

What's new in NSS 3.12.\*- New Shared DBs

NSS has introduced NEW Shared Databases based on SQLite in NSS 3.12.x. 
Motivation for introducing these new Shared Databases were :
  • ability to edit NSS databases without stopping server and
  • servers want to share DBs.

Advantages of these Shared DBs

Some experts from https://wiki.mozilla.org/NSS_Shared_DB

"NSS has been using an old version of the Berkeley Database as its database engine (commonly described in NSS documents as "DBM") has a number of limitations. One of the most severe limitations concerns the number of processes that may share a database file. While any process has a DBM file open for writing, NO other process may access it in any way. Multiple processes may share a DBM database ONLY if they ALL access it READ-ONLY. Processes cannot share a DBM database file if ANY of them wants to update it.

Applications that want to share databases have resorted to these strategies:
\* Synchronized updates, with application down time : The applications share the database read-only. If any update is desired, all the applications are shut down, and a database update program performs the update, then all the applications are restarted in read-only mode. This results in undesirable downtime and desired database changes are delayed until the next interval in which such downtime is acceptable."
...

"The new databases will be called 'shareable' databases. They may or may not be shared by multiple processes, but they are all capable of being shared. "
...

Shareable DB files : cert9.db, key4.db, pkcs11.txt

  • Are based on SQLite3
  • Allows read write by multiple simultaneous processes
  • Not enabled by default, must be enabled. To be enable it, use environment variable NSS_DEFAULT_DB_TYPE or add "sql:" prefix in configDir.
  • certutil utility program can do upgrade i.e. convert old DB (cert8.db) to new DB(cert9.db). For automatic upgrade, NSS must be told to use SQL AND the databases must be opened for reading AND writing. If NSS is not told to use SQL, or if the databases are opened READ-ONLY, then no automatic upgrade takes place.

Different types of NSS DBs

\* Directory name string prefix "sql:", "dbm:", "extern:", "multiaccess:" OR
\* Environment variable NSS_DEFAULT_DB_TYPE "sql", "dbm", "extern"

where "dbm" is the old default Berkeley DB (cert8). 
      "sql" is the new sqlite3 (cert9) DB. 
      "extern" and "multiaccess" are now obsolete.

How to upgrade from cert8.db to cert9.db

You can either use environment variables or use sql: prefix in database directory parameter of certutil:
$export NSS_DEFAULT_DB_TYPE=sql
$certutil -K -d /tmp/nss -X

OR

$certutil -K -d sql:/tmp/nss -X
When you upgrade these are the files you get :
key3.db -> key4.db
cert8.db -> cert9.db
secmod.db -> pkcs11.txt
The contents of the pkcs11.txt files are basically identical to the contents of the old secmod.db, just not in the old Berkeley DB format. If you run the command "$modutil -dbdir DBDIR -rawlist" on an older secmod.db file, you should get output similar to what you see in pkcs11.txt.
 
  
 
  

What needs to be done in programs / C code

Either add  environment variable NSS_DEFAULT_DB_TYPE "sql"

NSS_Initialize call in https://developer.mozilla.org/en/NSS_Initialize
takes this "configDir" parameter as shown below :

    NSS_Initialize(configDir, "", "", "secmod.db", NSS_INIT_READONLY);


For cert9.db, change this first parameter to "sql:" + configDir (like "sql:/tmp/nss/") i.e. prefix "sql:" in the directory name where these NSS Databases exist.

This code will work with cert8.db as well if cert9.db is not present.

References

  1. https://wiki.mozilla.org/NSS_Shared_DB_Samples
  2. https://wiki.mozilla.org/NSS_Shared_DB_Howto
  3. https://wiki.mozilla.org/NSS_Shared_DB
  4. http://www.mail-archive.com/dev-tech-crypto@lists.mozilla.org/msg05282.html

        
    

Thursday Nov 11, 2010

What's new in NSS 3.12.\*- PKIX - Bridged CA, revocation flags and Policies

What's new in NSS 3.12.\* - PKIX - Bridge CA, revocation flags and Policies

Network Security Services (NSS) 3.12 has a new feature:

  • libpkix: an RFC 3280 Compliant Certificate Path Validation Library

Some terms

PKIX

"PKIX" refers to all these extensions and enhancements documented in RFC 5280. These may be grouped into three major categories:

  • Bridge CA
  • revocation flags
  • policies

CRL Distribution Points

Refer RRFC section 4.2.1.13. The CRL distribution points extension identifies how CRL information is obtained.

PKI

As per RFC 4158 Public Key Infrastructure (PKI) is the set of hardware, software, personnel, policy, and procedures used by a CA to issue and manage certificates.

cross-certificate

As per RFC 4158, cross-certificate is a certificate issued by one CA to another CA for the purpose of establishing a trust relationship between the two CAs.

As per RFC 5280, A cross-certificate is a certificate issued by one CA to another CA that contains a CA signature key used for issuing certificates.



PKI structures

Lets discuss the three PKI structures : Hierarchical, Mesh style structure, Bridge structure

Hierarchical PKI structure

In hierarchical PKI structure, a certificate chain starting with a Web Server "Server" certificate would lead to an "intermediate CA", then to a "root" CA whose certificate is present in the web browser.

It looks something like

     Root CA1

        |      

    Intermediate CA1

        |            

       EE1

So we can have only one possible certificate chain for any leaf certificate : EE1 -> Intermediate CA1 -> Root CA1.

Mesh style PKI structure

In a mesh style PKI, CA's authenticate each other and creates certificates for one other. CA1 certificate for CA2 and CA2 creates certificate for CA1. In case there are 'n' CAs the number of certificates will be n2

Example of Mesh style PKI

   CA1 ------ CA2

      \\            /

        CA3

As per RFC 4158, the CAs in this environment have peer relationships; they are neither superior nor subordinate to one another.

In a mesh, CAs in the PKI cross-certify. That is, each CA issues a certificate to, and is issued a certificate by, peer CAs in the PKI.  A mesh PKI that is fully cross-certified is called a full mesh. However, it is possible to architect and deploy a mesh PKI with a mixture of uni-directional and bi- directional cross-certifications (called a partial mesh).  Partial meshes may also include CAs that are not cross-certified with other CAs in the mesh.

Bridge PKI structure

In a bridged PKI, a certificate chain starting with a Web Server "Server" Certificate might lead to Intermediary Bridge CA certificate, then to possible two different trusted Anchors.

Example of Bridge PKI

         CA1                               CA2 

       |             \\                        /

       |                  \\                /

  ICA(keypair1)   Bridge CA  (keypair2- cert1 from CA1 and cert2 from CA2)
                                  |               

                                EE

As you can see "Bridge CA" has been issued certificate both by trust anchor "CA1" and trust anchor "CA2". Both these certificates have the same DN. So we can get two certificate chains for a single certificate: EE -> Bridge CA -> CA1 and EE -> Bridge CA -> CA2.

As per RFC 4158, each PKI only cross-certifies with one other CA (i.e., the Bridge CA), and the Bridge CA cross-certifies only once with each participating PKI.  As a result, the number of cross certified relationships in the bridged environment grows linearly with the number of PKIs whereas the number of cross-certified relationships in mesh architectures grows exponentially.


Bridge CA

Brige CA is a CA which has more than one certificates from different issuers. A single intermediate CA entity can have any number of certificates from different CAs. Each of these identities  all share the same DN.

As per RFC4158, A BrideCA is a nexus to establish trust paths among multiple PKIs. The Bridge CA cross-certifies with one CA in each participating PKI.

In NSS 3.11.\* certificate verification function were

  • CERT_VerifyCertNow
  • CERT_VerifyCert
  • CERT_VerifyCertificate
  • CERT_VerifyCertificateNow
  • CERT_VerifyCACertForUsage
In NSS 3.12.\* a new certificate verification function CERT_PKIXVerifyCert as added which should be used to replace above mentioned calls.

Scenario show casing the difference between old NSS call CERT_VerifyCertNow and the new PKIX call CERT_PKIXVerifyCert

I wrote a sample program(server.cpp) . It runs on a certificate nicknamed "EE" (generated by Bridge CA),  both the old NSS call CERT_VerifyCertNow and the corresponding new PKIX call CERT_PKIXVerifyCert.

I wrote a script run-tests.sh which creates CA1, CA2 and 2 certificates for Bridge CA and EE cert. Then it modifies trust flags of CA1 and CA2 and runs server program on it. 

When we set a C trust flag on a certificate - It means that this certificate should be treated like a CA certificate but also should be treated as root certificate we trust. When NSS clients/server validates certificate chain we can stop right there.

Because CA1 and CA2 root CA certificates are self-signed certificates, if we do not add "C" trust flags in them, we get SEC_ERROR_UNTRUSTED_ISSUER error.

When we remove "C" the trust flag of either of the CA certificates CA1 or CA2 and the test case starts failing, we know that the server program uses that chain. When we mark the trust flags of either of the CA certificates CA1 or CA2 as "C" and the test starts to pass so we know that the server program uses that chain.

You can see only ONE of CA1 or CA2 chain works in old CERT_VerifyCertNow() but in the new call CERT_PKIXVerifyCert() both the CA1 and CA2 chains work.

Look at the last few lines of output of the script run-tests.sh to confirm that.

$sh run-tests.sh
...
=====================================
Running tests with trust flags - CA2-trusted CA1-trusted
certutil ouput is
Certificate Nickname              Trust Attributes
CA1                               CTu,Cu,Cu
CA2                               CTu,Cu,Cu
Bridge                              u,u,u
Bridge                              u,u,u
EE                                  u,u,u
CERT_PKIXVerifyCert(EE) - PASSED.
CERT_VerifyCertNow(EE) - PASSED.
=====================================
Running tests with trust flags - CA2-not trusted CA1-trusted
certutil ouput is
Certificate Nickname              Trust Attributes
Bridge                                u,u,u
Bridge                                u,u,u
EE                                    u,u,u
CA1                                  Cu,u,u
CA2                                   u,u,u
CERT_PKIXVerifyCert(EE) - PASSED.
ERROR: CERT_VerifyCertNow(EE) - FAILED !! 
( as it uses chain EE-> Bridge ->CA2, CA2 is not trusted due to absence of flag "C")
      Error = -8172   SEC_ERROR_UNTRUSTED_ISSUER 
      Peer's certificate issuer has been marked as not trusted by the user.
=====================================
Running tests with trust flags - CA2-trusted CA1-not trusted
certutil ouput is
Certificate Nickname                Trust Attributes
Bridge                                  u,u,u
Bridge                                  u,u,u
EE                                      u,u,u
CA2                                    Cu,u,u
CA1                                     u,u,u
CERT_PKIXVerifyCert(EE) - PASSED.
CERT_VerifyCertNow(EE) - PASSED.
 (as it uses chain EE->Bridge -> CA2 and CA2 is trusted due to flag "C")
=====================================

 
  


PKIX and revocation flags

The function CERT_PKIXVerifyCert gives the server much greater control over how the certificate validation is done. For example, it allows the server to decide

  • what to do about revocation checking for leaf certificates or intermediate CA certs in a certificate chain.
  • whether to use CRLs or OCSP or both, and in which order of preference.
  • whether to use local CRLs or OCSP or fetch it from network or both.
  • whether to skip it, or attempt it but not require it, or to absolutely require it.
  • whether to ask it to attempt to fetch missing certificates from certificate chains, and/or to fetch CRLs, and/or to fetch OCSP responses.
  • whether to impose any certificate policy requirements on certificates.

CERT_PKIxVerifyCert takes an array of input parameters for tuning these. For details refer

http://mxr.mozilla.org/security/source/security/nss/lib/certdb/certt.h#887

http://mxr.mozilla.org/security/source/security/nss/lib/certdb/certt.h#1010


PKIX and Policies

Refer RFC520 section 4.2.1.4 for information about policies.

When verifying a certificate chain (using CERT_PKIXVerifyCert()) it is possible to pass as input, a given policy oid that must be met. The certification validation will fail if the requested policy is not in place.

It is also possible to request a list of all policies(OIDs) which were found to be valid.(a list of OIDs).

 
  


Thanx to Jyri and Nelson for helping me understand these concepts. 

References



Makefile to compile http://blogs.sun.com/meena/resource/server.cpp

SECURITY_DIR=/export2/NSS_3.12.8/
all:
    CC -g  -I$(SECURITY_DIR)/include -L$(SECURITY_DIR)/lib -lnspr4 -lnss3 server.cpp -o server

And then run http://blogs.sun.com/meena/resource/run-tests.sh.txt

About

Meena Vyas

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today