]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
auth: Allow using NSS as crypto library.
authorTommi Virtanen <tommi.virtanen@dreamhost.com>
Fri, 11 Mar 2011 18:28:58 +0000 (10:28 -0800)
committerTommi Virtanen <tommi.virtanen@dreamhost.com>
Fri, 11 Mar 2011 21:13:39 +0000 (13:13 -0800)
Added new configure flag --with-nss that enables this. NSS is also
automatically used if it is available and CryptoPP is not; use
--without-nss to explicitly forbid this.

No change on rgw crypto yet; rgw won't build without CryptoPP for now.

NSS initialization is in a static constructor for now. All it does is
set some values on in-memory data structures, so as long as no (other)
static constructor tries to use it, everything should just work. While
this could be moved to common_init, there are several other context
initialization steps with NSS, and a later refactoring to share the
results of these can just include NSS init as its first operation, at
practically no cost.

Signed-off-by: Tommi Virtanen <tommi.virtanen@dreamhost.com>
configure.ac
src/Makefile.am
src/auth/Crypto.cc

index 9206ad60d17bab27b7d7359a3182ccf6bf4decf5..b324500d4e14d4b83749e7f4b878ca9ca8f2a22e 100644 (file)
@@ -31,8 +31,56 @@ AC_PROG_LIBTOOL
 # Checks for libraries.
 AC_CHECK_LIB([m], [pow], [true], AC_MSG_FAILURE([libm not found]))
 AC_CHECK_LIB([pthread], [pthread_create], [true], AC_MSG_FAILURE([libpthread not found]))
-PKG_CHECK_MODULES([CRYPTOPP], [libcrypto++], [], [
-       AC_SEARCH_LIBS([_ZTIN8CryptoPP14CBC_EncryptionE], [crypto++ cryptopp], [true], AC_MSG_FAILURE([libcrypto++ not found]), [-lpthread])])
+
+# Find some crypto library for us to use, while letting user to decide which one to use.
+AC_ARG_WITH([cryptopp],
+       [AS_HELP_STRING([--with-cryptopp], [Use cryptographic functions from cryptopp])],
+       [],
+       [with_cryptopp=check])
+have_cryptopp=no
+# this looks clumsy but it's just if A then { success } else { if B then success }
+AS_IF([test "x$with_cryptopp" != "xno"],
+    [PKG_CHECK_MODULES([CRYPTOPP],
+           [libcrypto++],
+           [have_cryptopp=yes],
+           [AC_SEARCH_LIBS([_ZTIN8CryptoPP14CBC_EncryptionE], [crypto++ cryptopp],
+                   [have_cryptopp=yes],
+                   [true],
+                   [-lpthread])])])
+# bail out if given explicit --with-cryptopp
+if test "x$have_cryptopp" = "xno" -a "x$with_cryptopp" != "xcheck" -a "x$with_cryptopp" != "xno"; then
+    AC_MSG_FAILURE([--with-cryptopp was given, but library was not found])
+fi
+
+AC_ARG_WITH([nss],
+       [AS_HELP_STRING([--with-nss], [Use cryptographic functions from nss])],
+       [],
+       [with_nss=check])
+have_nss=no
+AS_IF([test "x$with_nss" != "xno"],
+    [PKG_CHECK_MODULES([NSS], [nss], [have_nss=yes], [true])])
+# bail out if given explicit --with-nss
+if test "x$have_nss" = "xno" -a "x$with_nss" != "xcheck" -a "x$with_nss" != "xno"; then
+    AC_MSG_FAILURE([--with-nss was given, but library was not found])
+fi
+
+# now decide which crypto library to really use
+if test "x$have_cryptopp" = "xyes"; then
+    AC_MSG_NOTICE([using cryptopp for cryptography])
+    AC_DEFINE([USE_CRYPTOPP], [1], [Define if using CryptoPP.])
+    AC_SUBST([CRYPTO_CFLAGS], [$CRYPTOPP_CFLAGS])
+    AC_SUBST([CRYPTO_CXXFLAGS], [$CRYPTOPP_CXXFLAGS])
+    AC_SUBST([CRYPTO_LIBS], [$CRYPTOPP_LIBS])
+elif test "x$have_nss" = "xyes"; then
+    AC_MSG_NOTICE([using nss for cryptography])
+    AC_DEFINE([USE_NSS], [1], [Define if using NSS.])
+    AC_SUBST([CRYPTO_CFLAGS], [$NSS_CFLAGS])
+    # this needs CFLAGS too in practise to get the includes right. ugly.
+    AC_SUBST([CRYPTO_CXXFLAGS], [$NSS_CFLAGS $NSS_CXXFLAGS])
+    AC_SUBST([CRYPTO_LIBS], [$NSS_LIBS])
+else
+    AC_MSG_FAILURE([no suitable crypto library found])
+fi
 
 # profiler?
 AC_ARG_WITH([profiler],
index 2ce1aa123cf65915dcb44e89eac16e526786f5f9..cbea816b5df3b8f2bc8f7e1ef9900b6ff52697b8 100644 (file)
@@ -26,19 +26,19 @@ endif
 
 # monitor
 cmon_SOURCES = cmon.cc msg/SimpleMessenger.cc
-cmon_LDADD = libmon.a libcrush.a libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+cmon_LDADD = libmon.a libcrush.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += cmon
 
 # osd
 cosd_SOURCES = cosd.cc msg/SimpleMessenger.cc objclass/class_debug.cc \
               objclass/class_api.cc
-cosd_LDADD = libosd.a libos.a libcrush.a libcommon.a -ldl -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+cosd_LDADD = libosd.a libos.a libcrush.a libcommon.a -ldl -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += cosd
 cosd_CXXFLAGS = ${AM_CXXFLAGS}
 
 # mds
 cmds_SOURCES = cmds.cc msg/SimpleMessenger.cc
-cmds_LDADD = libmds.a libosdc.a libcrush.a libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+cmds_LDADD = libmds.a libosdc.a libcrush.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += cmds
 cmds_CXXFLAGS = ${AM_CXXFLAGS}
 
@@ -47,7 +47,7 @@ ceph_SOURCES = \
        msg/SimpleMessenger.cc \
        tools/ceph.cc \
        tools/common.cc
-ceph_LDADD = libcrush.a libcommon.a -ledit -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+ceph_LDADD = libcrush.a libcommon.a -ledit -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 ceph_CXXFLAGS = ${AM_CXXFLAGS}
 
 if WITH_GTK2
@@ -75,7 +75,7 @@ gceph_SOURCES = \
        tools/common.cc \
        tools/gceph.cc \
        tools/gui.cc
-gceph_LDADD = libcrush.a libcommon.a -ledit -lpthread -lm $(CRYPTOPP_LIBS) \
+gceph_LDADD = libcrush.a libcommon.a -ledit -lpthread -lm $(CRYPTO_LIBS) \
        $(GTKMM_LIBS) $(EXTRALIBS)
 gceph_CXXFLAGS = ${AM_CXXFLAGS} $(GTKMM_CFLAGS) \
        -DCEPH_TOOL_GUIDIR="\"${ceph_tool_guidir}\""
@@ -83,17 +83,17 @@ bin_PROGRAMS += gceph
 endif
 
 cconf_SOURCES = cconf.cc
-cconf_LDADD = libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+cconf_LDADD = libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 cauthtool_SOURCES = cauthtool.cc
-cauthtool_LDADD = libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+cauthtool_LDADD = libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += ceph cconf cauthtool
 
 monmaptool_SOURCES = monmaptool.cc
-monmaptool_LDADD = libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+monmaptool_LDADD = libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 crushtool_SOURCES = crushtool.cc
-crushtool_LDADD = libcrush.a libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+crushtool_LDADD = libcrush.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 osdmaptool_SOURCES = osdmaptool.cc
-osdmaptool_LDADD = libcrush.a libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+osdmaptool_LDADD = libcrush.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += monmaptool crushtool osdmaptool
 
 mount_ceph_SOURCES = mount/mount.ceph.c
@@ -109,7 +109,7 @@ bin_PROGRAMS += librados-config
 
 # synthetic client
 csyn_SOURCES = csyn.cc msg/SimpleMessenger.cc
-csyn_LDADD = libclient.a libosdc.a libcrush.a libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+csyn_LDADD = libclient.a libosdc.a libcrush.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += csyn
 
 core: cmon cosd cmds ceph cephfs librados-config cconf monmaptool osdmaptool crushtool csyn
@@ -118,7 +118,7 @@ core: cmon cosd cmds ceph cephfs librados-config cconf monmaptool osdmaptool cru
 # fuse targets?
 if WITH_FUSE
 cfuse_SOURCES = cfuse.cc msg/SimpleMessenger.cc client/fuse_ll.cc
-cfuse_LDADD = -lfuse libclient.a libosdc.a libcrush.a libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+cfuse_LDADD = -lfuse libclient.a libosdc.a libcrush.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 cfuse_CXXFLAGS = ${AM_CXXFLAGS}
 bin_PROGRAMS += cfuse
 
@@ -146,30 +146,30 @@ endif # WITH_TCMALLOC
 if WITH_DEBUG
 
 psim_SOURCES = psim.cc
-psim_LDADD = libcrush.a libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+psim_LDADD = libcrush.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += psim
 
 testmsgr_SOURCES = testmsgr.cc msg/SimpleMessenger.cc
-testmsgr_LDADD = libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+testmsgr_LDADD = libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += testmsgr
 
 test_ioctls_SOURCES = client/test_ioctls.c
 bin_PROGRAMS += test_ioctls
 
 dumpjournal_SOURCES = dumpjournal.cc msg/SimpleMessenger.cc
-dumpjournal_LDADD = libosdc.a libcrush.a libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+dumpjournal_LDADD = libosdc.a libcrush.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 dupstore_SOURCES = dupstore.cc
-dupstore_LDADD = libos.a libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+dupstore_LDADD = libos.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 streamtest_SOURCES = streamtest.cc
-streamtest_LDADD = libos.a libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+streamtest_LDADD = libos.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += dumpjournal dupstore streamtest
 
 test_trans_SOURCES = test_trans.cc
-test_trans_LDADD = libos.a libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+test_trans_LDADD = libos.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += test_trans
 
 testsnaps_SOURCES = test/osd/TestSnaps.cc
-testsnaps_LDADD = librados.la -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+testsnaps_LDADD = librados.la -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += testsnaps
 
 endif
@@ -198,19 +198,19 @@ libceph_la_SOURCES = \
        msg/SimpleMessenger.cc \
        ${libcommon_a_SOURCES} \
        ${libosdc_a_SOURCES}
-libceph_la_CFLAGS = ${AM_CFLAGS}
-libceph_la_CXXFLAGS= ${AM_CXXFLAGS}
-libceph_la_LIBADD = libcrush.la -lpthread $(CRYPTOPP_LIBS) $(EXTRALIBS)
+libceph_la_CFLAGS= ${CRYPTO_CFLAGS} ${AM_CFLAGS}
+libceph_la_CXXFLAGS= ${CRYPTO_CXXFLAGS} ${AM_CXXFLAGS}
+libceph_la_LIBADD = libcrush.la -lpthread $(CRYPTO_LIBS) $(EXTRALIBS)
 libceph_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 -export-symbols-regex '^ceph_.*'
 lib_LTLIBRARIES += libceph.la
 
 if WITH_DEBUG
 testceph_SOURCES = client/testceph.cc
-testceph_LDADD = libceph.la libcrush.la -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+testceph_LDADD = libceph.la libcrush.la -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += testceph
 
 testtimers_SOURCES = test/TestTimers.cc
-testtimers_LDADD = libceph.la libcrush.la -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+testtimers_LDADD = libceph.la libcrush.la -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += testtimers
 
 testdout_streambuf_SOURCES = test/TestDoutStreambuf.cc
@@ -230,15 +230,15 @@ librados_SOURCES = \
        osdc/Objecter.cc \
        ${libcommon_a_SOURCES}
 librados_la_SOURCES = ${librados_SOURCES}
-librados_la_CFLAGS = ${AM_CFLAGS}
-librados_la_CXXFLAGS = ${AM_CXXFLAGS}
-librados_la_LIBADD = libcrush.la -lpthread $(CRYPTOPP_LIBS) $(EXTRALIBS)
+librados_la_CFLAGS = ${CRYPTO_CFLAGS} ${AM_CFLAGS}
+librados_la_CXXFLAGS = ${CRYPTO_CXXFLAGS} ${AM_CXXFLAGS}
+librados_la_LIBADD = libcrush.la -lpthread $(CRYPTO_LIBS) $(EXTRALIBS)
 librados_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0 -export-symbols-regex '^rados_.*'
 lib_LTLIBRARIES += librados.la
 
 librados_a_SOURCES = ${librados_SOURCES}
-librados_a_CFLAGS = ${AM_CFLAGS}
-librados_a_CXXFLAGS = ${AM_CXXFLAGS}
+librados_a_CFLAGS = ${CRYPTO_CFLAGS} ${AM_CFLAGS}
+librados_a_CXXFLAGS = ${CRYPTO_CXXFLAGS} ${AM_CXXFLAGS}
 
 # librbd
 librbd_SOURCES = \
@@ -247,7 +247,7 @@ librbd_SOURCES = \
 librbd_la_SOURCES = ${librbd_SOURCES}
 librbd_la_CFLAGS = ${AM_CFLAGS}
 librbd_la_CXXFLAGS = ${AM_CXXFLAGS}
-librbd_la_LIBADD = librados.la libcrush.la -lpthread $(CRYPTOPP_LIBS) $(EXTRALIBS)
+librbd_la_LIBADD = librados.la libcrush.la -lpthread $(CRYPTO_LIBS) $(EXTRALIBS)
 librbd_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 -export-symbols-regex '^rbd_.*'
 lib_LTLIBRARIES += librbd.la
 
@@ -256,31 +256,31 @@ librbd_a_CFLAGS = ${AM_CFLAGS}
 librbd_a_CXXFLAGS = ${AM_CXXFLAGS}
 
 rados_SOURCES = rados.cc
-rados_LDADD = librados.la -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+rados_LDADD = librados.la -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += rados
 
 if WITH_DEBUG
 testrados_SOURCES = testrados.c
-testrados_LDADD = librados.la -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+testrados_LDADD = librados.la -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 testradospp_SOURCES = testradospp.cc
 testradospp_LDADD = librados.la -lpthread -lm
 radosacl_SOURCES = radosacl.cc
-radosacl_LDADD = librados.la -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+radosacl_LDADD = librados.la -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += testrados testradospp radosacl
 endif
 
 rbd_SOURCES = rbd.cc common/fiemap.cc
 rbd_CXXFLAGS = ${AM_CXXFLAGS}
-rbd_LDADD = librbd.la librados.la libcrush.la -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+rbd_LDADD = librbd.la librados.la libcrush.la -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += rbd
 
 if WITH_DEBUG
 testlibrbd_SOURCES = testlibrbd.c
 testlibrbd_LDADD = librbd.la librados.la libcrush.la -lpthread -lm \
-                  $(CRYPTOPP_LIBS) $(EXTRALIBS)
+                  $(CRYPTO_LIBS) $(EXTRALIBS)
 testlibrbdpp_SOURCES = testlibrbdpp.cc
 testlibrbdpp_LDADD = librbd.la librados.la libcrush.la -lpthread -lm \
-                    $(CRYPTOPP_LIBS) $(EXTRALIBS)
+                    $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += testlibrbd testlibrbdpp
 endif
 
@@ -299,21 +299,21 @@ libradosgw_a_CXXFLAGS = ${AM_CXXFLAGS}
 # lib_LTLIBRARIES += libradosgw.a
 
 radosgw_SOURCES = rgw/rgw_main.cc
-radosgw_LDADD = libradosgw.a librados.a libcrush.a -lfcgi -lexpat -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+radosgw_LDADD = libradosgw.a librados.a libcrush.a -lfcgi -lexpat -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 radosgw_CXXFLAGS = ${AM_CXXFLAGS}
 radosgw_admin_SOURCES = rgw/rgw_admin.cc
-radosgw_admin_LDADD = libradosgw.a librados.a libcrush.a -lfcgi -lexpat -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+radosgw_admin_LDADD = libradosgw.a librados.a libcrush.a -lfcgi -lexpat -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += radosgw radosgw_admin
 endif
 
 if WITH_DEBUG
 testcrypto_SOURCES = testcrypto.cc
-testcrypto_LDADD = libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+testcrypto_LDADD = libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 testcrypto_CXXFLAGS = ${AM_CXXFLAGS}
 bin_PROGRAMS += testcrypto
 
 testkeys_SOURCES = testkeys.cc
-testkeys_LDADD = libmon.a libcommon.a -lpthread -lm $(CRYPTOPP_LIBS) $(EXTRALIBS)
+testkeys_LDADD = libmon.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 testkeys_CXXFLAGS = ${AM_CXXFLAGS}
 bin_PROGRAMS += testkeys
 endif
@@ -518,6 +518,9 @@ libcommon_a_SOURCES = \
        ./ceph_ver.c \
        $(libcommon_files)
 
+libcommon_a_CFLAGS= ${CRYPTO_CFLAGS} ${AM_CFLAGS}
+libcommon_a_CXXFLAGS= ${CRYPTO_CXXFLAGS} ${AM_CXXFLAGS}
+
 # this list ommits the ceph_ver.c file
 libcommon_files = \
        auth/AuthAuthorizeHandler.cc \
index bbce59b3d738e14aafa5ff0c0df32047acabedcc..d9b599d5681cc4d4c917780c08cc3ae91330cd8f 100644 (file)
  * 
  */
 
+#include <assert.h>
 #include "Crypto.h"
-#include <cryptopp/modes.h>
-#include <cryptopp/aes.h>
-#include <cryptopp/filters.h>
+#ifdef USE_CRYPTOPP
+# include <cryptopp/modes.h>
+# include <cryptopp/aes.h>
+# include <cryptopp/filters.h>
+#elif USE_NSS
+# include <nspr.h>
+# include <nss.h>
+# include <pk11pub.h>
+#endif
 
 #include "include/ceph_fs.h"
 #include "common/config.h"
@@ -82,12 +89,137 @@ int CryptoNone::decrypt(bufferptr& secret, const bufferlist& in, bufferlist& out
 
 
 // ---------------------------------------------------
-#define AES_KEY_LEN     ((size_t)CryptoPP::AES::DEFAULT_KEYLENGTH)
-#define AES_BLOCK_LEN   ((size_t)CryptoPP::AES::BLOCKSIZE)
+#ifdef USE_CRYPTOPP
+# define AES_KEY_LEN     ((size_t)CryptoPP::AES::DEFAULT_KEYLENGTH)
+# define AES_BLOCK_LEN   ((size_t)CryptoPP::AES::BLOCKSIZE)
+#elif USE_NSS
+// when we say AES, we mean AES-128
+# define AES_KEY_LEN   16
+# define AES_BLOCK_LEN   16
+
+static int nss_aes_operation(CK_ATTRIBUTE_TYPE op, bufferptr& secret, const bufferlist& in, bufferlist& out) {
+  const CK_MECHANISM_TYPE mechanism = CKM_AES_CBC_PAD;
+
+  // sample source said this has to be at least size of input + 8,
+  // but i see 15 still fail with SEC_ERROR_OUTPUT_LEN
+  bufferptr out_tmp(in.length()+16);
+  int err = -EINVAL;
+
+  PK11SlotInfo *slot;
+
+  slot = PK11_GetBestSlot(mechanism, NULL);
+  if (!slot) {
+    dout(0) << "cannot find NSS slot to use: " << PR_GetError() << dendl;
+    goto err;
+  }
+
+  SECItem keyItem;
+
+  keyItem.type = siBuffer;
+  keyItem.data = (unsigned char*)secret.c_str();
+  keyItem.len = secret.length();
+
+  PK11SymKey *key;
+
+  key = PK11_ImportSymKey(slot, mechanism, PK11_OriginUnwrap, CKA_ENCRYPT,
+                         &keyItem, NULL);
+  if (!key) {
+    dout(0) << "cannot convert AES key for NSS: " << PR_GetError() << dendl;
+    goto err_slot;
+  }
+
+  SECItem ivItem;
+
+  ivItem.type = siBuffer;
+  // losing constness due to SECItem.data; IV should never be
+  // modified, regardless
+  ivItem.data = (unsigned char*)CEPH_AES_IV;
+  ivItem.len = sizeof(CEPH_AES_IV);
+
+  SECItem *param;
+
+  param = PK11_ParamFromIV(mechanism, &ivItem);
+  if (!param) {
+    dout(0) << "cannot set NSS IV param: " << PR_GetError() << dendl;
+    goto err_key;
+  }
+
+  PK11Context *ctx;
+
+  ctx = PK11_CreateContextBySymKey(mechanism, op, key, param);
+  if (!ctx) {
+    dout(0) << "cannot create NSS context: " << PR_GetError() << dendl;
+    goto err_param;
+  }
+
+  SECStatus ret;
+  int written;
+  // in is const, and PK11_CipherOp is not; C++ makes this hard to cheat,
+  // so just copy it to a temp buffer, at least for now
+  unsigned in_len;
+  unsigned char *in_buf;
+  in_len = in.length();
+  in_buf = (unsigned char*)malloc(in_len);
+  if (!in_buf) {
+    dout(0) << "NSS out of memory" << dendl;
+    err = -ENOMEM;
+    goto err_ctx;
+  }
+  in.copy(0, in_len, (char*)in_buf);
+  ret = PK11_CipherOp(ctx, (unsigned char*)out_tmp.c_str(), &written, out_tmp.length(),
+                     in_buf, in.length());
+  free(in_buf);
+  if (ret != SECSuccess) {
+    dout(0) << "NSS AES failed: " << PR_GetError() << dendl;
+    goto err_op;
+  }
+
+  unsigned int written2;
+  ret = PK11_DigestFinal(ctx, (unsigned char*)out_tmp.c_str()+written, &written2,
+                        out_tmp.length()-written);
+  if (ret != SECSuccess) {
+    dout(0) << "NSS AES final round failed: " << PR_GetError() << dendl;
+    goto err_op;
+  }
+
+  PK11_DestroyContext(ctx, PR_TRUE);
+  out_tmp.set_length(written + written2);
+  out.append(out_tmp);
+  return out_tmp.length();
+
+ err_op:
+ err_ctx:
+  PK11_DestroyContext(ctx, PR_TRUE);
+ err_param:
+  SECITEM_FreeItem(param, PR_TRUE);
+ err_key:
+  PK11_FreeSymKey(key);
+ err_slot:
+  PK11_FreeSlot(slot);
+ err:
+  return err;
+}
+
+#else
+# error "No supported crypto implementation found."
+#endif
 
 class CryptoAES : public CryptoHandler {
 public:
-  CryptoAES() {}
+  CryptoAES() {
+#ifdef USE_NSS
+    SECStatus ret;
+    ret = NSS_NoDB_Init(NULL);
+    if (ret != SECSuccess) {
+      dout(0) << "initializing NSS crypto library failed (code "
+             << PR_GetError() << "), aborting" << dendl;
+      exit(1);
+    }
+
+    
+#endif
+  }
+
   ~CryptoAES() {}
   int create(bufferptr& secret);
   int validate_secret(bufferptr& secret);
@@ -117,40 +249,49 @@ int CryptoAES::validate_secret(bufferptr& secret)
 
 int CryptoAES::encrypt(bufferptr& secret, const bufferlist& in, bufferlist& out)
 {
-  const unsigned char *key = (const unsigned char *)secret.c_str();
-  const unsigned char *in_buf;
-
   if (secret.length() < AES_KEY_LEN) {
     dout(0) << "key is too short" << dendl;
     return false;
   }
-  string ciphertext;
-  CryptoPP::AES::Encryption aesEncryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
-  CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption( aesEncryption, (const byte*)CEPH_AES_IV );
-  CryptoPP::StringSink *sink = new CryptoPP::StringSink(ciphertext);
-  if (!sink)
-    return false;
-  CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, sink);
-
-  for (std::list<bufferptr>::const_iterator it = in.buffers().begin(); 
-       it != in.buffers().end(); it++) {
-    in_buf = (const unsigned char *)it->c_str();
-
-    stfEncryptor.Put(in_buf, it->length());
-  }
-  try {
-    stfEncryptor.MessageEnd();
-  } catch (CryptoPP::Exception& e) {
-    dout(0) << "encryptor.MessageEnd::Exception: " << e.GetWhat() << dendl;
-    return false;
+#ifdef USE_CRYPTOPP
+  {
+    const unsigned char *key = (const unsigned char *)secret.c_str();
+    const unsigned char *in_buf;
+
+    string ciphertext;
+    CryptoPP::AES::Encryption aesEncryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
+    CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption( aesEncryption, (const byte*)CEPH_AES_IV );
+    CryptoPP::StringSink *sink = new CryptoPP::StringSink(ciphertext);
+    if (!sink)
+      return false;
+    CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, sink);
+
+    for (std::list<bufferptr>::const_iterator it = in.buffers().begin();
+        it != in.buffers().end(); it++) {
+      in_buf = (const unsigned char *)it->c_str();
+
+      stfEncryptor.Put(in_buf, it->length());
+    }
+    try {
+      stfEncryptor.MessageEnd();
+    } catch (CryptoPP::Exception& e) {
+      dout(0) << "encryptor.MessageEnd::Exception: " << e.GetWhat() << dendl;
+      return false;
+    }
+    out.append((const char *)ciphertext.c_str(), ciphertext.length());
   }
-  out.append((const char *)ciphertext.c_str(), ciphertext.length());
-
+#elif USE_NSS
+  // the return type may be int but this CryptoAES::encrypt returns bools
+  return (nss_aes_operation(CKA_ENCRYPT, secret, in, out) >= 0);
+#else
+# error "No supported crypto implementation found."
+#endif
   return true;
 }
 
 int CryptoAES::decrypt(bufferptr& secret, const bufferlist& in, bufferlist& out)
 {
+#ifdef USE_CRYPTOPP
   const unsigned char *key = (const unsigned char *)secret.c_str();
 
   CryptoPP::AES::Decryption aesDecryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
@@ -176,6 +317,11 @@ int CryptoAES::decrypt(bufferptr& secret, const bufferlist& in, bufferlist& out)
 
   out.append((const char *)decryptedtext.c_str(), decryptedtext.length());
   return decryptedtext.length();
+#elif USE_NSS
+  return nss_aes_operation(CKA_DECRYPT, secret, in, out);
+#else
+# error "No supported crypto implementation found."
+#endif
 }