Ticket #714: nss.diff

File nss.diff, 5.5 KB (added by Matěj Cepl <mcepl@…>, at 2010-11-06T18:11:38Z)

making NSS build work

  • configure

    diff --git a/configure b/configure
    index ff68da8..be06d6a 100755
    a b EOF 
    288288
    289289detect_nss()
    290290{
    291         if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG mozilla-nss; then
     291        if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG nss; then
    292292                cat<<EOF>>Makefile.settings
    293 EFLAGS+=`$PKG_CONFIG --libs mozilla-nss`
    294 CFLAGS+=`$PKG_CONFIG --cflags mozilla-nss`
     293EFLAGS+=`$PKG_CONFIG --libs nss`
     294CFLAGS+=`$PKG_CONFIG --cflags nss`
    295295EOF
    296296               
    297297                ssl=nss
    if [ "$ret" = "0" ]; then 
    426426        exit 1
    427427fi;
    428428
    429 if [ "$msn" = "1" -a "$ssl" != "openssl" -a "$ssl" != "gnutls" ]; then
     429if [ "$msn" = "1" -a "$ssl" != "openssl" -a "$ssl" != "nss" -a "$ssl" != "gnutls" ]; then
    430430        # Needed for MSN only. OpenSSL exports nice cipher functions already,
    431431        # in case of GnuTLS we should be able to use gcrypt. Otherwise, use
    432432        # built-in stuff. (Since right now those are the only two supported
  • lib/ssl_nss.c

    diff --git a/lib/ssl_nss.c b/lib/ssl_nss.c
    index b0e2f9f..63a47f5 100644
    a b  
    3333#include <prio.h>
    3434#include <sslproto.h>
    3535#include <nss.h>
     36#include <pk11pub.h>
    3637#include <private/pprio.h>
    3738#include <ssl.h>
     39#include <seccomon.h>
    3840#include <secerr.h>
    3941#include <sslerr.h>
    4042
    struct scd 
    5254};
    5355
    5456static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
     57static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond );
    5558
    5659
    5760static SECStatus nss_auth_cert (void *arg, PRFileDesc *socket, PRBool checksig, PRBool isserver)
    void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data 
    121124        return( conn );
    122125}
    123126
     127static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond )
     128{
     129        struct scd *conn = data;
     130
     131        return ssl_connected( conn, conn->fd, B_EV_IO_WRITE );
     132}
     133
     134void *ssl_starttls( int fd, ssl_input_function func, gpointer data )
     135{
     136        struct scd *conn = g_new0( struct scd, 1 );
     137
     138        conn->fd = fd;
     139        conn->func = func;
     140        conn->data = data;
     141
     142        /* This function should be called via a (short) timeout instead of
     143           directly from here, because these SSL calls are *supposed* to be
     144           *completely* asynchronous and not ready yet when this function
     145           (or *_connect, for examle) returns. Also, errors are reported via
     146           the callback function, not via this function's return value.
     147
     148           In short, doing things like this makes the rest of the code a lot
     149           simpler. */
     150
     151        b_timeout_add( 1, ssl_starttls_real, conn );
     152
     153        return conn;
     154}
     155
    124156static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
    125157{
    126158        struct scd *conn = data;
    b_input_condition ssl_getdirection( void *conn ) 
    200232        /* Just in case someone calls us, let's return the most likely case: */
    201233        return B_EV_IO_READ;
    202234}
     235
     236size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len,
     237    const unsigned char *input, size_t input_len, const unsigned char *iv,
     238    unsigned char **res)
     239{
     240  int output_length = 0;
     241
     242  CK_MECHANISM_TYPE cipherMech;
     243  PK11SlotInfo* slot = NULL;
     244  PK11SymKey* SymKey = NULL;
     245  SECItem* SecParam = NULL;
     246  PK11Context* EncContext = NULL;
     247  SECItem keyItem, ivItem;
     248  SECStatus rv1, rv2;
     249  int tmp1_outlen, tmp2_outlen;
     250
     251  if (!initialized)
     252    {
     253      ssl_init();
     254    }
     255
     256  *res = g_new0(unsigned char, 1024);
     257
     258  cipherMech = CKM_DES3_CBC_PAD;
     259  slot = PK11_GetBestSlot(cipherMech, NULL);
     260
     261  if (slot == NULL)
     262    {
     263      fprintf(stderr, "Unable to find security device (err %d)\n",
     264          PR_GetError());
     265      goto out;
     266    }
     267
     268  // Converts "raw key" into a key object.
     269  keyItem.type = siBuffer;
     270  keyItem.data = (unsigned char*)key;
     271  keyItem.len = key_len;
     272
     273  SymKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, CKA_ENCRYPT,
     274                             &keyItem, NULL);
     275
     276  if (SymKey == NULL)
     277  {
     278    fprintf(stderr, "Failure to import key into NSS (err %d)\n",
     279            PR_GetError());
     280    goto out;
     281  }
     282
     283  /* set up the PKCS11 encryption paramters.
     284   * when not using CBC mode, ivItem.data and ivItem.len can be 0, or you
     285   * can simply pass NULL for the iv parameter in PK11_ParamFromIV func
     286   */
     287  ivItem.type = siBuffer;
     288  ivItem.data = iv;
     289  ivItem.len = strlen(iv); // ??? Is it right? FIXME
     290  SecParam = PK11_ParamFromIV(cipherMech, &ivItem);
     291  if (SecParam == NULL)
     292  {
     293    fprintf(stderr, "Failure to set up PKCS11 param (err %d)\n",
     294            PR_GetError());
     295    goto out;
     296  }
     297
     298  /* ========================= START SECTION ============================= */
     299  /* If using the the same key and iv over and over, stuff before this     */
     300  /* section and after this section needs to be done only ONCE             */
     301  /* ENCRYPT data into buf1. buf1 len must be atleast (data len + 8) */
     302  tmp1_outlen = tmp2_outlen = 0;
     303
     304  /* Create cipher context */
     305  EncContext = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT,
     306                                          SymKey, SecParam);
     307  rv1 = PK11_CipherOp(EncContext, res, &tmp1_outlen, sizeof(res),
     308                      input, input_len+1);
     309  rv2 = PK11_DigestFinal(EncContext, res+tmp1_outlen, &tmp2_outlen,
     310                         sizeof(res)-tmp1_outlen);
     311  PK11_DestroyContext(EncContext, PR_TRUE);
     312  output_length = tmp1_outlen + tmp2_outlen;
     313  if (rv1 != SECSuccess || rv2 != SECSuccess)
     314    goto out;
     315
     316  return output_length;
     317
     318  out:
     319    if (SymKey)
     320      PK11_FreeSymKey(SymKey);
     321    if (SecParam)
     322      SECITEM_FreeItem(SecParam, PR_TRUE);
     323}