Blob Blame History Raw
diff -up bitlbee-3.0.1/configure.des3 bitlbee-3.0.1/configure
--- bitlbee-3.0.1/configure.des3	2010-12-28 16:07:35.074260735 +0100
+++ bitlbee-3.0.1/configure	2010-12-28 16:07:35.082260713 +0100
@@ -429,10 +431,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
diff -up bitlbee-3.0.1/lib/ssl_nss.c.des3 bitlbee-3.0.1/lib/ssl_nss.c
--- bitlbee-3.0.1/lib/ssl_nss.c.des3	2010-12-28 16:07:35.077260726 +0100
+++ bitlbee-3.0.1/lib/ssl_nss.c	2010-12-28 16:09:02.408014610 +0100
@@ -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;
+}