URL: https://github.com/freeipa/freeipa/pull/1678
Author: rcritten
 Title: #1678: Manual rebase of OTP FIPS mode fixes
Action: opened

PR body:
"""
Manual rebase of PR https://github.com/freeipa/freeipa/pull/1621 to the ipa-4-5 
branch
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/1678/head:pr1678
git checkout pr1678
From 4e7013b55340e001ec60bcc45a312adbf601118c 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.

https://pagure.io/freeipa/issue/7168

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 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 00044acc5278b6f098d82eceae27f2b9e9249519 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.

https://pagure.io/freeipa/issue/7168

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 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 c66f0980f0..a6e423f949 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 6670d416126a8fd61e1044601d812d00a880b7c3 Mon Sep 17 00:00:00 2001
From: Nathaniel McCallum <npmccal...@redhat.com>
Date: Mon, 26 Feb 2018 09:48:22 -0500
Subject: [PATCH 3/3] Revert "Don't allow OTP or RADIUS in FIPS mode"

This reverts commit 16a952a0a44a0ebee97029ea1d2f6b7593dd2622.

OTP now works in FIPS mode. RADIUS can be made to be compliant by wrapping
traffic in a VPN.

https://pagure.io/freeipa/issue/7168
https://pagure.io/freeipa/issue/7243

Reviewed-By: Rob Crittenden <rcrit...@redhat.com>
---
 ipaserver/plugins/baseuser.py |  6 +-----
 ipaserver/plugins/config.py   | 16 ----------------
 2 files changed, 1 insertion(+), 21 deletions(-)

diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py
index bb8a73ded0..76a112fa28 100644
--- a/ipaserver/plugins/baseuser.py
+++ b/ipaserver/plugins/baseuser.py
@@ -30,9 +30,7 @@
     LDAPAddMember, LDAPRemoveMember,
     LDAPAddAttributeViaOption, LDAPRemoveAttributeViaOption,
     add_missing_object_class)
-from ipaserver.plugins.service import (
-   validate_certificate, validate_realm, normalize_principal)
-from ipaserver.plugins.config import check_fips_auth_opts
+from ipaserver.plugins.service import (validate_realm, normalize_principal)
 from ipalib.request import context
 from ipalib import _
 from ipalib.constants import PATTERN_GROUPUSER_NAME
@@ -478,7 +476,6 @@ def pre_common_callback(self, ldap, dn, entry_attrs, attrs_list, *keys,
                             **options):
         assert isinstance(dn, DN)
         set_krbcanonicalname(entry_attrs)
-        check_fips_auth_opts(fips_mode=self.api.env.fips_mode, **options)
         self.obj.convert_usercertificate_pre(entry_attrs)
 
     def post_common_callback(self, ldap, dn, entry_attrs, *keys, **options):
@@ -602,7 +599,6 @@ def pre_common_callback(self, ldap, dn, entry_attrs, attrs_list, *keys,
         assert isinstance(dn, DN)
         add_sshpubkey_to_attrs_pre(self.context, attrs_list)
 
-        check_fips_auth_opts(fips_mode=self.api.env.fips_mode, **options)
         self.check_namelength(ldap, **options)
 
         self.check_mail(entry_attrs)
diff --git a/ipaserver/plugins/config.py b/ipaserver/plugins/config.py
index c9033fa8e7..ce15e6096f 100644
--- a/ipaserver/plugins/config.py
+++ b/ipaserver/plugins/config.py
@@ -85,20 +85,6 @@
 
 register = Registry()
 
-
-def check_fips_auth_opts(fips_mode, **options):
-    """
-    OTP and RADIUS are not allowed in FIPS mode since they use MD5
-    checksums (OTP uses our RADIUS responder daemon ipa-otpd).
-    """
-    if 'ipauserauthtype' in options and fips_mode:
-        if ('otp' in options['ipauserauthtype'] or
-                'radius' in options['ipauserauthtype']):
-            raise errors.InvocationError(
-                'OTP and RADIUS authentication in FIPS is '
-                'not yet supported')
-
-
 @register()
 class config(LDAPObject):
     """
@@ -412,8 +398,6 @@ class config_mod(LDAPUpdate):
 
     def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
         assert isinstance(dn, DN)
-        check_fips_auth_opts(fips_mode=self.api.env.fips_mode, **options)
-
         if 'ipadefaultprimarygroup' in entry_attrs:
             group=entry_attrs['ipadefaultprimarygroup']
             try:
_______________________________________________
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