Re: PR_Close and PR_Shutdown hang if an SSL socket is blocking on Read

2007-07-10 Thread Yahel Zamir
Oops, I forgot some details - we are using NSS-3.11.4 and NSPR-4.6.4
on a RedHat Linux with Kernel 2.4, using gcc 3.4.5.

On Jul 10, 5:36 pm, Yahel Zamir <[EMAIL PROTECTED]> wrote:
> Hi,
>
> I have encountered a problem in using SSL sockets in blocking mode. My
> application is multi threaded, with one thread waiting to read and
> another that is waiting to write. Upon some external input, a third
> thread tries to shutdown the connection and then close the socket.
> However, calling PR_Shutdown or PR_Close never returns from
> SSL_LOCK_READER(ss).
>
> Following are a simple client and server that demonstrate the problem
> (search the client for 999 and the server for "delayed_close").
>
> Thanks,
> Yahel Zamir,
> SW Engineer at CWNT
>
> ===
> M_DIST = /usr/home/yahel/programs/nss/mozilla/dist
>
> M_DIST_LINUX = ${M_DIST}/Linux2.4_x86_glibc_PTH_DBG.OBJ
>
> M_INC =  -I${M_DIST_LINUX}/include
> M_INC += -I${M_DIST}/public/nss
> M_INC += -I${M_DIST}/private/nss # for error strings
>
> M_FLAGS = -g -Wall -pthread
>
> M_LIBS = -L${M_DIST_LINUX}/lib
> M_LIBS += -lssl3 -lnss3 -lnspr4 -lplds4 -lplc4 -lsoftokn3
> M_LIBS += -lfreebl3 -lsectool -lpthread -ldl -lc
>
> all: server client
> @echo done
>
> clean:
> rm -f client server client.o server.o
>
> server.o: server.c
> gcc server.c -c ${M_FLAGS} ${M_INC} -o server.o
>
> client.o: client.c
> gcc client.c -c ${M_FLAGS} ${M_INC} -o client.o
>
> server: server.o
> gcc server.o ${M_FLAGS} ${M_LIBS} -o server
>
> client: client.o
> gcc client.o ${M_FLAGS} ${M_LIBS} -o client
>
> ===
>
> // client.c
> // 
>
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include  // a private API needed for SECU_Strerror
>
> static char *s_progName = NULL;
> static char *s_password = NULL;
> static char *s_hostName = NULL;
>
> /*
>  * errWarn()
>  *
>  * Print a warning message for NSS and NSPR errors.
>  * More detailed explanations for the error can be found at:
>  *http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslerr.html
>  */
> static void
> errWarn(char * funcString)
> {
> PRErrorCode perr = PR_GetError();
> const char * errString = SECU_Strerror(perr);
> fprintf(stderr, "%s: %s returned error %d (%s)\n", s_progName,
> funcString, perr, errString);
> return;
>
> }
>
> static void
> errExit(char * funcString)
> {
> errWarn(funcString);
> exit(3);
>
> }
>
> static void
> Usage(const char *progName)
> {
> fprintf(stderr, "Usage: %s hostname -n cert_name -p port -d cert_dir -
> w password \n", progName);
> exit(1);
>
> }
>
> /* fakePasswd()
>  *
>  * This function is our custom password handler that is called by
>  * SSL when retreiving private certs and keys from the database.
> Returns a
>  * pointer to a string that with a password for the database. Password
> pointer
>  * should point to dynamically allocated memory that will be freed
> later.
>  * We set "arg" to give the correct password, using
> SSL_SetPKCS11PinArg().
>  */
> char *
> fakePasswd(PK11SlotInfo *info, PRBool retry, void *arg)
> {
> char * passwd = NULL;
>
> if ((!retry) && (arg != NULL)) {
> passwd = PL_strdup((char *)arg);
> }
>
> return passwd;
>
> }
>
> /* Function:  setupSSLSocket()
>  *
>  * Purpose:  Configure a socket for SSL.
>  */
> PRFileDesc *
> setupSSLSocket()
> {
> PRFileDesc *sslSocket;
> PRFileDesc *tcpSocket;
> SECStatus   secStatus;
> PRSocketOptionData  socketOption;
> PRStatusprStatus;
>
> tcpSocket = PR_NewTCPSocket();
> if (tcpSocket == NULL) {
> errWarn("PR_NewTCPSocket");
> return NULL;
> }
>
> // Ensure the socket is blocking.
> socketOption.option = PR_SockOpt_Nonblocking;
> socketOption.value.non_blocking = PR_FALSE;
>
> prStatus = PR_SetSocketOption(tcpSocket, &socketOption);
> if (prStatus != PR_SUCCESS) {
> errWarn("PR_SetSocketOption");
> PR_Close(tcpSocket);
> return NULL;
> }
>
> sslSocket = SSL_ImportFD(NULL, tcpSocket);
> if (sslSocket == NULL) {
> errWarn("SSL_ImportFD");
> PR_Close(tcpSocket);
> return NULL;
> }
>
> // ensure original socket is not used
> tcpSocket = NULL;
>
> do {
>
> // handshake as client
> secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT,
> PR_TRUE);
> if (secStatus != SECSuccess) {
> errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT");
> break;
> }
>
> // enable full duplex
> secStatus = SSL_OptionSet(sslSocket, SSL_ENABLE_FDX, PR_TRUE);
> if (secStatus != SECSuccess) {
> errWarn("SSL_OptionSet(SSL_ENABLE_FDX)");
> break;
> }
>
> // allow communication without encryption (YZ - must be onl

PR_Close and PR_Shutdown hang if an SSL socket is blocking on Read

2007-07-10 Thread Yahel Zamir
Hi,

I have encountered a problem in using SSL sockets in blocking mode. My
application is multi threaded, with one thread waiting to read and
another that is waiting to write. Upon some external input, a third
thread tries to shutdown the connection and then close the socket.
However, calling PR_Shutdown or PR_Close never returns from
SSL_LOCK_READER(ss).

Following are a simple client and server that demonstrate the problem
(search the client for 999 and the server for "delayed_close").

Thanks,
Yahel Zamir,
SW Engineer at CWNT

===
M_DIST = /usr/home/yahel/programs/nss/mozilla/dist

M_DIST_LINUX = ${M_DIST}/Linux2.4_x86_glibc_PTH_DBG.OBJ

M_INC =  -I${M_DIST_LINUX}/include
M_INC += -I${M_DIST}/public/nss
M_INC += -I${M_DIST}/private/nss # for error strings

M_FLAGS = -g -Wall -pthread

M_LIBS = -L${M_DIST_LINUX}/lib
M_LIBS += -lssl3 -lnss3 -lnspr4 -lplds4 -lplc4 -lsoftokn3
M_LIBS += -lfreebl3 -lsectool -lpthread -ldl -lc

all: server client
@echo done

clean:
rm -f client server client.o server.o

server.o: server.c
gcc server.c -c ${M_FLAGS} ${M_INC} -o server.o

client.o: client.c
gcc client.c -c ${M_FLAGS} ${M_INC} -o client.o

server: server.o
gcc server.o ${M_FLAGS} ${M_LIBS} -o server

client: client.o
gcc client.o ${M_FLAGS} ${M_LIBS} -o client

===

// client.c
// 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include  // a private API needed for SECU_Strerror

static char *s_progName = NULL;
static char *s_password = NULL;
static char *s_hostName = NULL;

/*
 * errWarn()
 *
 * Print a warning message for NSS and NSPR errors.
 * More detailed explanations for the error can be found at:
 * http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslerr.html
 */
static void
errWarn(char * funcString)
{
PRErrorCode perr = PR_GetError();
const char * errString = SECU_Strerror(perr);
fprintf(stderr, "%s: %s returned error %d (%s)\n", s_progName,
funcString, perr, errString);
return;
}

static void
errExit(char * funcString)
{
errWarn(funcString);
exit(3);
}

static void
Usage(const char *progName)
{
fprintf(stderr, "Usage: %s hostname -n cert_name -p port -d cert_dir -
w password \n", progName);
exit(1);
}

/* fakePasswd()
 *
 * This function is our custom password handler that is called by
 * SSL when retreiving private certs and keys from the database.
Returns a
 * pointer to a string that with a password for the database. Password
pointer
 * should point to dynamically allocated memory that will be freed
later.
 * We set "arg" to give the correct password, using
SSL_SetPKCS11PinArg().
 */
char *
fakePasswd(PK11SlotInfo *info, PRBool retry, void *arg)
{
char * passwd = NULL;

if ((!retry) && (arg != NULL)) {
passwd = PL_strdup((char *)arg);
}

return passwd;
}


/* Function:  setupSSLSocket()
 *
 * Purpose:  Configure a socket for SSL.
 */
PRFileDesc *
setupSSLSocket()
{
PRFileDesc *sslSocket;
PRFileDesc *tcpSocket;
SECStatus   secStatus;
PRSocketOptionData  socketOption;
PRStatusprStatus;

tcpSocket = PR_NewTCPSocket();
if (tcpSocket == NULL) {
errWarn("PR_NewTCPSocket");
return NULL;
}

// Ensure the socket is blocking.
socketOption.option = PR_SockOpt_Nonblocking;
socketOption.value.non_blocking = PR_FALSE;

prStatus = PR_SetSocketOption(tcpSocket, &socketOption);
if (prStatus != PR_SUCCESS) {
errWarn("PR_SetSocketOption");
PR_Close(tcpSocket);
return NULL;
}

sslSocket = SSL_ImportFD(NULL, tcpSocket);
if (sslSocket == NULL) {
errWarn("SSL_ImportFD");
PR_Close(tcpSocket);
return NULL;
}

// ensure original socket is not used
tcpSocket = NULL;

do {

// handshake as client
secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT,
PR_TRUE);
if (secStatus != SECSuccess) {
errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT");
break;
}

// enable full duplex
secStatus = SSL_OptionSet(sslSocket, SSL_ENABLE_FDX, PR_TRUE);
if (secStatus != SECSuccess) {
errWarn("SSL_OptionSet(SSL_ENABLE_FDX)");
break;
}

// allow communication without encryption (YZ - must be only
upon client request)
if (SECSuccess != SSL_CipherPrefSet(sslSocket,
SSL_RSA_WITH_NULL_SHA, PR_TRUE)
|| SECSuccess != SSL_CipherPrefSet(sslSocket,
SSL_RSA_WITH_NULL_MD5, PR_TRUE)) {
errWarn("SSL_CipherPrefSet - Null Cipher");
break;
}

secStatus = SSL_SetPKCS11PinArg(sslSocket, s_password);
if (secStatus != SECSuccess) {
errWarn("SSL_SetPKCS11PinArg");
break;
}

secStatus = SSL_SetURL(sslSocket, s

Re: PR_Close and PR_Shutdown hang if an SSL socket is blocking on Read

2007-07-10 Thread Wan-Teh Chang
Yahel Zamir wrote:
> Hi,
> 
> I have encountered a problem in using SSL sockets in blocking mode. My
> application is multi threaded, with one thread waiting to read and
> another that is waiting to write. Upon some external input, a third
> thread tries to shutdown the connection and then close the socket.
> However, calling PR_Shutdown or PR_Close never returns from
> SSL_LOCK_READER(ss).

Calling PR_Close then is a programming error.  While one thread
is blocking in PR_Recv, another thread cannot call PR_Close on
that socket because PR_Close will free the PRFileDesc structure
representing that socket.  That is, one thread should not free
the memory still in use by another thread.  I believe the
SSL_LOCK_READER(ss) macros are intended to detect or prevent
such programming errors from crashing NSS.

Off the top of my head, I don't know why we can't call
PR_Shutdown while another thread is blocking in PR_Recv.
The presence of the SSL_LOCK_READER(ss) macro in
ssl_Shutdown (http://lxr.mozilla.org/mozilla1.8/ident?i=ssl_Shutdown)
shows it is also considered a programming error.  I just
don't know why.

Wan-Teh
___
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto


Re: Getting public/private keys into/out of NSS

2007-07-10 Thread Dave Townsend
Hi Bob, thanks for all your help by the way, got me much further so far.

Robert Relyea wrote:
> You really only want to store and retrieve the private keys if you you 
> need to transport them (or back them up).  Doing the latter needs to be 
> handled carefully, and can be a source of errors in your protocol.

This is fine for my uses I think. So long as the private key is 
somewhere safe that is backupable (the nss certificate database is fine 
by me) then thats all good.

> A better way to handle it (if you absolutely must use bare keys), is 
> store your private keys as persistant keys. You can use the KeyID and 
> the slot the key is stored in to find the key again (PK11_FindKeyByID to 
> find it PK11_GetLowLevelKeyIDForPrivatekey() to get the KeyID).

I'm not totally sure I follow you. Let me just quickyl explain what I am 
wanting to present to the user. They should pretty much not have to 
worry about certificates or anything like that. All that matters is that 
they can create a public/private key pair and that my app can show them 
a list of what key pairs they have created before and then use them.

I have this pretty much working but I think I've slightly hacked it. 
What I've done is assigned a nickname to the private key when it's 
created. That seems nice until I come to retrieve the key, it seems 
there isnt a way to retrieve a key by nickname instead I just have to 
enumerate all keys till I find the one with the nickname. This isn't so 
bad, there shouldn't be many keys but maybe I'm going about this the 
wrong way?

> Usually NSS uses the certificate. There are functions to help you find 
> the most appropriate certificate, and then from that certificate find 
> the private key that is associated with it.

I probably have the wrong view of certificates, but my understanding is 
that they have all sorts of other associated data about then, CN etc and 
more crucially expiries. Is this right or am I wrong? In which case I'd 
happily switch over to certificates if that helps me achieve my above goal.

One other final thing I'm stumbling over is key and hash types. I 
recognise the names RSA and DSA but is there a particular advantage of 
using one over the other? And likewise when I'm signing my data should I 
hash it using MD5, SHA-1 or any of the other SHAs. I think I read 
somewhere that RSA keys should be used with MD5 hashes and DSA with 
SHA-1, is this right?

Dave
___
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto


Re: Getting public/private keys into/out of NSS

2007-07-10 Thread Robert Relyea

Dave Townsend wrote:

Hi Bob, thanks for all your help by the way, got me much further so far.

Robert Relyea wrote:
  
You really only want to store and retrieve the private keys if you you 
need to transport them (or back them up).  Doing the latter needs to be 
handled carefully, and can be a source of errors in your protocol.



This is fine for my uses I think. So long as the private key is 
somewhere safe that is backupable (the nss certificate database is fine 
by me) then thats all good.
  
Then I would just use the database and use extracting the key as a 
backup. That would also allow storing the keys in a token without any 
modification of your code.
  
A better way to handle it (if you absolutely must use bare keys), is 
store your private keys as persistant keys. You can use the KeyID and 
the slot the key is stored in to find the key again (PK11_FindKeyByID to 
find it PK11_GetLowLevelKeyIDForPrivatekey() to get the KeyID).



I'm not totally sure I follow you. Let me just quickyl explain what I am 
wanting to present to the user. They should pretty much not have to 
worry about certificates or anything like that. All that matters is that 
they can create a public/private key pair and that my app can show them 
a list of what key pairs they have created before and then use them.


I have this pretty much working but I think I've slightly hacked it. 
What I've done is assigned a nickname to the private key when it's 
created. That seems nice until I come to retrieve the key, it seems 
there isnt a way to retrieve a key by nickname instead I just have to 
enumerate all keys till I find the one with the nickname. This isn't so 
bad, there shouldn't be many keys but maybe I'm going about this the 
wrong way?
  
No, there usually aren't very many keys. KeyID's are a unique handle to 
the private keys, nickname/labels aren't always set.
  
Usually NSS uses the certificate. There are functions to help you find 
the most appropriate certificate, and then from that certificate find 
the private key that is associated with it.



I probably have the wrong view of certificates, but my understanding is 
that they have all sorts of other associated data about then, CN etc and 
more crucially expiries. Is this right or am I wrong? In which case I'd 
happily switch over to certificates if that helps me achieve my above goal.
  
Certs are basically bindings of identity to a public key, so the cert 
has the user's identity (in the form of a Distinguished name), they 
public key, some house keeping (the identity of the CA that verified the 
cert, expiration, etc.),  usually some optional  information telling 
what the certificate is good for (signing, encryption, code signing, 
authentication, etc.), and a signature. Usually the user doesn't bother 
looking at the cert itself, the cert contains enough information to 
allow the software to process it and verify it's validity. They help 
with thing like validating a signature. With a certificate, I can 
validate a signature was signed by the identity specified in the 
certificate without having to trust a bare public keys. Most protocols 
that need to scale beyond 20 or 30 people need to use something like 
certificates.
One other final thing I'm stumbling over is key and hash types. I 
recognise the names RSA and DSA but is there a particular advantage of 
using one over the other? 
RSA and DSA have different performance characteristics, RSA has a fairly 
fast verification compared to signing. It's also more widely understood. 
At one time DSA was the only one of the two that were not patent encumbered.
And likewise when I'm signing my data should I 
hash it using MD5, SHA-1 or any of the other SHAs. I think I read 
somewhere that RSA keys should be used with MD5 hashes and DSA with 
SHA-1, is this right?
  
I would always use at least SHA-1. DSA can only use exactly SHA-1. Both 
MD-5 and SHA-1 have been shown to be weak against collision attacks 
(attacks in which I can generate 2 different messages that hash to the 
same value), though they are still strong against preimage (trying to 
calculate a second message the hashes to the same value of a given 
message). If you're protocol depends on collision resistance, then you 
should think about using SHA-256 or greater. The only issue is there is 
still a fair amount of code that does not support the larger hash 
functions, so if you need to interoperate with that older code you will 
need to stick to SHA-1, otherwise I strongly encourage you to use the 
longer SHA algorithms.


bob

Dave
___
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto
  




smime.p7s
Description: S/MIME Cryptographic Signature
___
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto