Index: bitlbee-3.0.3/configure =================================================================== --- bitlbee-3.0.3.orig/configure +++ bitlbee-3.0.3/configure @@ -433,10 +433,10 @@ if [ "$ret" = "0" ]; then exit 1 fi; -if [ "$msn" = "1" -a "$ssl" != "openssl" -a "$ssl" != "gnutls" ]; then - # Needed for MSN only. OpenSSL exports nice cipher functions already, +if [ "$msn" = "1" -a "$ssl" != "openssl" -a "$ssl" != "gnutls" -a "$ssl" != "nss" ]; then + # Needed for MSN only. OpenSSL and NSS export nice cipher functions already, # in case of GnuTLS we should be able to use gcrypt. Otherwise, use - # built-in stuff. (Since right now those are the only two supported + # built-in stuff. (Since right now those are the only three supported # SSL modules anyway, this is mostly unnecessary.) echo 'DES=des.o' >> Makefile.settings fi Index: bitlbee-3.0.3/lib/ssl_nss.c =================================================================== --- bitlbee-3.0.3.orig/lib/ssl_nss.c +++ bitlbee-3.0.3/lib/ssl_nss.c @@ -39,6 +39,7 @@ #include <seccomon.h> #include <secerr.h> #include <sslerr.h> +#include <assert.h> int ssl_errno = 0; @@ -238,3 +239,91 @@ b_input_condition ssl_getdirection( void /* Just in case someone calls us, let's return the most likely case: */ return B_EV_IO_READ; } + +size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, + const unsigned char *input, size_t input_len, const unsigned char *iv, + unsigned char **res) +{ +#define CIPHER_MECH CKM_DES3_CBC +#define MAX_OUTPUT_LEN 72 + + int len1; + unsigned int len2; + + PK11Context *ctx = NULL; + PK11SlotInfo *slot = NULL; + SECItem keyItem; + SECItem ivItem; + SECItem *secParam = NULL; + PK11SymKey *symKey = NULL; + + size_t rc; + SECStatus rv; + + if (!initialized) { + ssl_init(); + } + + keyItem.data = (unsigned char *) key; + keyItem.len = key_len; + + slot = PK11_GetBestSlot(CIPHER_MECH, NULL); + if (slot == NULL) { + fprintf(stderr, "PK11_GetBestSlot failed (err %d)\n", PR_GetError()); + rc = 0; + goto out; + } + + symKey = PK11_ImportSymKey(slot, CIPHER_MECH, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL); + if (symKey == NULL) { + fprintf(stderr, "PK11_ImportSymKey failed (err %d)\n", PR_GetError()); + rc = 0; + goto out; + } + + ivItem.data = (unsigned char *) iv; + /* See msn_soap_passport_sso_handle_response in protocols/msn/soap.c */ + ivItem.len = 8; + + secParam = PK11_ParamFromIV(CIPHER_MECH, &ivItem); + if (secParam == NULL) { + fprintf(stderr, "PK11_ParamFromIV failed (err %d)\n", PR_GetError()); + rc = 0; + goto out; + } + + ctx = PK11_CreateContextBySymKey(CIPHER_MECH, CKA_ENCRYPT, symKey, secParam); + if (ctx == NULL) { + fprintf(stderr, "PK11_CreateContextBySymKey failed (err %d)\n", PR_GetError()); + rc = 0; + goto out; + } + + *res = g_new0(unsigned char, MAX_OUTPUT_LEN); + + rv = PK11_CipherOp(ctx, *res, &len1, MAX_OUTPUT_LEN, (unsigned char *) input, input_len); + if (rv != SECSuccess) { + fprintf(stderr, "PK11_CipherOp failed (err %d)\n", PR_GetError()); + rc = 0; + goto out; + } + + assert(len1 <= MAX_OUTPUT_LEN); + + rv = PK11_DigestFinal(ctx, *res + len1, &len2, (unsigned int) MAX_OUTPUT_LEN - len1); + if (rv != SECSuccess) { + fprintf(stderr, "PK11_DigestFinal failed (err %d)\n", PR_GetError()); + rc = 0; + goto out; + } + + rc = len1 + len2; + +out: + if (ctx) PK11_DestroyContext(ctx, PR_TRUE); + if (symKey) PK11_FreeSymKey(symKey); + if (secParam) SECITEM_FreeItem(secParam, PR_TRUE); + if (slot) PK11_FreeSlot(slot); + + return rc; +}