URL: https://github.com/freeipa/freeipa/pull/1621
Author: npmccallum
 Title: #1621: OTP FIPS mode fixes
Action: opened

PR body:
"""
The following patches add various fixes for using OTP on a server running in 
FIPS mode.
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/1621/head:pr1621
git checkout pr1621
From 4c14a5eb61e01c682674275cb31f6ef2fcaf2999 Mon Sep 17 00:00:00 2001
From: Nathaniel McCallum <npmccal...@redhat.com>
Date: Wed, 21 Feb 2018 23:39:55 -0500
Subject: [PATCH 1/3] Fix OTP validation in FIPS mode

NSS doesn't allow keys to be loaded directly in FIPS mode. To work around this,
we encrypt the input key using an ephemeral key and then unwrap the encrypted
key.
---
 daemons/ipa-slapi-plugins/libotp/hotp.c | 47 +++++++++++++++++++++++++++++++--
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/daemons/ipa-slapi-plugins/libotp/hotp.c b/daemons/ipa-slapi-plugins/libotp/hotp.c
index 619bc63ab1..0c9de96d37 100644
--- a/daemons/ipa-slapi-plugins/libotp/hotp.c
+++ b/daemons/ipa-slapi-plugins/libotp/hotp.c
@@ -46,6 +46,7 @@
 #include <time.h>
 
 #include <nss.h>
+#include <blapit.h>
 #include <pk11pub.h>
 #include <hasht.h>
 #include <prnetdb.h>
@@ -66,6 +67,49 @@ static const struct {
     { }
 };
 
+static PK11SymKey *
+import_key(PK11SlotInfo *slot, CK_MECHANISM_TYPE mech, SECItem *key)
+{
+    uint8_t ct[(key->len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE];
+    uint8_t iv[AES_BLOCK_SIZE] = {};
+    SECItem ivitem = { .data = iv, .len = sizeof(iv), .type = siBuffer };
+    SECItem ctitem = { .data = ct, .len = sizeof(ct), .type = siBuffer };
+    PK11SymKey *ekey = NULL;
+    PK11SymKey *skey = NULL;
+
+    /* Try to import the key directly. */
+    skey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap,
+                             CKA_SIGN, key, NULL);
+    if (skey)
+        return skey;
+
+    /* If we get here, we are probably in FIPS mode. Let's encrypt the key so
+     * that we can unseal it instead of loading it directly. */
+
+    /* Generate an ephemeral key. */
+    ekey = PK11_TokenKeyGenWithFlags(slot, CKM_AES_CBC_PAD, NULL,
+                                     AES_128_KEY_LENGTH, NULL,
+                                     CKF_ENCRYPT | CKF_UNWRAP,
+                                     PK11_ATTR_SESSION |
+                                     PK11_ATTR_PRIVATE |
+                                     PK11_ATTR_SENSITIVE, NULL);
+    if (!ekey)
+        goto egress;
+
+    /* Encrypt the input key. */
+    if (PK11_Encrypt(ekey, CKM_AES_CBC_PAD, &ivitem, ctitem.data, &ctitem.len,
+                     ctitem.len, key->data, key->len) != SECSuccess)
+        goto egress;
+
+    /* Unwrap the input key. */
+    skey = PK11_UnwrapSymKey(ekey, CKM_AES_CBC_PAD, &ivitem,
+                             &ctitem, mech, CKA_SIGN, key->len);
+
+egress:
+    PK11_FreeSymKey(ekey);
+    return skey;
+}
+
 /*
  * This code is mostly cargo-cult taken from here:
  *   http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn5.html
@@ -90,8 +134,7 @@ static bool hmac(SECItem *key, CK_MECHANISM_TYPE mech, const SECItem *in,
         }
     }
 
-    symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap,
-                               CKA_SIGN, key, NULL);
+    symkey = import_key(slot, mech, key);
     if (symkey == NULL)
         goto done;
 

From c66a93f8f5f3c307995d3dbe5c0388259d93c37d Mon Sep 17 00:00:00 2001
From: Nathaniel McCallum <npmccal...@redhat.com>
Date: Thu, 22 Feb 2018 14:04:10 -0500
Subject: [PATCH 2/3] Increase the default token key size

The previous default token key size would fail in FIPS mode for the sha384 and
sha512 algorithms. With the updated key size, the default will work in all
cases.
---
 ipaserver/plugins/otptoken.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ipaserver/plugins/otptoken.py b/ipaserver/plugins/otptoken.py
index 24815c108f..d94ae49fff 100644
--- a/ipaserver/plugins/otptoken.py
+++ b/ipaserver/plugins/otptoken.py
@@ -72,7 +72,7 @@
 }
 
 # NOTE: For maximum compatibility, KEY_LENGTH % 5 == 0
-KEY_LENGTH = 20
+KEY_LENGTH = 35
 
 class OTPTokenKey(Bytes):
     """A binary password type specified in base32."""

From 9b754396ce989006d4712d29bd06b78efb79732c Mon Sep 17 00:00:00 2001
From: Nathaniel McCallum <npmccal...@redhat.com>
Date: Thu, 22 Feb 2018 14:21:27 -0500
Subject: [PATCH 3/3] Add log message for OTP validation context

When running in FIPS mode, NSS enforces key sizes on HMAC. If the input keys
are too small, the creation of the context will fail. We don't want this
failure to occur silently so that admins can see they need to increase their
key sizes.
---
 daemons/ipa-slapi-plugins/libotp/hotp.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/daemons/ipa-slapi-plugins/libotp/hotp.c b/daemons/ipa-slapi-plugins/libotp/hotp.c
index 0c9de96d37..9875412661 100644
--- a/daemons/ipa-slapi-plugins/libotp/hotp.c
+++ b/daemons/ipa-slapi-plugins/libotp/hotp.c
@@ -45,6 +45,9 @@
 #include "hotp.h"
 #include <time.h>
 
+#include <slapi-plugin.h>
+#include "../common/util.h"
+
 #include <nss.h>
 #include <blapit.h>
 #include <pk11pub.h>
@@ -139,8 +142,10 @@ static bool hmac(SECItem *key, CK_MECHANISM_TYPE mech, const SECItem *in,
         goto done;
 
     ctx = PK11_CreateContextBySymKey(mech, CKA_SIGN, symkey, &param);
-    if (ctx == NULL)
+    if (ctx == NULL) {
+        LOG_FATAL("Error creating OTP validation context (key too small?)!\n");
         goto done;
+    }
 
     s = PK11_DigestBegin(ctx);
     if (s != SECSuccess)
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org

Reply via email to