[Freeipa-devel] [freeipa PR#1621][opened] OTP FIPS mode fixes

2018-02-22 Thread npmccallum via FreeIPA-devel
   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 
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 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -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 
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 
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 
 
+#include 
+#include "../common/u

[Freeipa-devel] [freeipa PR#884][opened] ipa-otptoken-import: Make PBKDF2 refer to the pkcs5 namespace

2017-06-20 Thread npmccallum via FreeIPA-devel
   URL: https://github.com/freeipa/freeipa/pull/884
Author: npmccallum
 Title: #884: ipa-otptoken-import: Make PBKDF2 refer to the pkcs5 namespace
Action: opened

PR body:
"""
For some unknown reason, when I wrote the ipa-otptoken-import script
I used bad input data which had the PBKDF2 parameters in the wrong
XML namespace. I have corrected this input data to match RFC 6030.
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/884/head:pr884
git checkout pr884
From 0d083d23eb9fb5b85dec5fc53aaa9ab223981f30 Mon Sep 17 00:00:00 2001
From: Nathaniel McCallum 
Date: Tue, 20 Jun 2017 10:31:15 -0400
Subject: [PATCH] ipa-otptoken-import: Make PBKDF2 refer to the pkcs5 namespace

For some unknown reason, when I wrote the ipa-otptoken-import script
I used bad input data which had the PBKDF2 parameters in the wrong
XML namespace. I have corrected this input data to match RFC 6030.
---
 ipaserver/install/ipa_otptoken_import.py  | 11 ++-
 ipatests/test_ipaserver/data/pskc-figure7.xml | 16 
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/ipaserver/install/ipa_otptoken_import.py b/ipaserver/install/ipa_otptoken_import.py
index 2580e2cfc9..b97803b648 100644
--- a/ipaserver/install/ipa_otptoken_import.py
+++ b/ipaserver/install/ipa_otptoken_import.py
@@ -52,6 +52,7 @@ class ValidationError(Exception):
 
 def fetchAll(element, xpath, conv=lambda x: x):
 return [conv(e) for e in element.xpath(xpath, namespaces={
+"pkcs5": "http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#";,
 "pskc": "urn:ietf:params:xml:ns:keyprov:pskc",
 "xenc11": "http://www.w3.org/2009/xmlenc11#";,
 "xenc": "http://www.w3.org/2001/04/xmlenc#";,
@@ -175,18 +176,18 @@ def derive(self, masterkey):
 
 class PBKDF2KeyDerivation(XMLKeyDerivation):
 def __init__(self, enckey):
-params = fetch(enckey, "./xenc11:DerivedKey/xenc11:KeyDerivationMethod/xenc11:PBKDF2-params")
+params = fetch(enckey, "./xenc11:DerivedKey/xenc11:KeyDerivationMethod/pkcs5:PBKDF2-params")
 if params is None:
 raise ValueError("XML file is missing PBKDF2 parameters!")
 
 salt = fetch(
-params, "./xenc11:Salt/xenc11:Specified/text()", base64.b64decode)
+params, "./pkcs5:Salt/pkcs5:Specified/text()", base64.b64decode)
 itrs = fetch(
-params, "./xenc11:IterationCount/text()", int)
+params, "./pkcs5:IterationCount/text()", int)
 klen = fetch(
-params, "./xenc11:KeyLength/text()", int)
+params, "./pkcs5:KeyLength/text()", int)
 hmod = fetch(
-params, "./xenc11:PRF/@Algorithm", convertHMACType, hashes.SHA1)
+params, "./pkcs5:PRF/@Algorithm", convertHMACType, hashes.SHA1)
 
 if salt is None:
 raise ValueError("XML file is missing PBKDF2 salt!")
diff --git a/ipatests/test_ipaserver/data/pskc-figure7.xml b/ipatests/test_ipaserver/data/pskc-figure7.xml
index 1fb04fc319..808e272a54 100644
--- a/ipatests/test_ipaserver/data/pskc-figure7.xml
+++ b/ipatests/test_ipaserver/data/pskc-figure7.xml
@@ -8,14 +8,14 @@
 
   http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#pbkdf2";>
-
-  
-Ej7/PEpyEpw=
-  
-  1000
-  16
-  
-
+
+  
+Ej7/PEpyEpw=
+  
+  1000
+  16
+  
+
   
   
 
___
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org