Skip to content

Commit

Permalink
Fix OTP validation in FIPS mode
Browse files Browse the repository at this point in the history
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 <rcritten@redhat.com>
Reviewed-By: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
  • Loading branch information
npmccallum authored and tiran committed Mar 14, 2018
1 parent 6073a69 commit 52c5998
Showing 1 changed file with 45 additions and 2 deletions.
47 changes: 45 additions & 2 deletions daemons/ipa-slapi-plugins/libotp/hotp.c
Expand Up @@ -46,6 +46,7 @@
#include <time.h>

#include <nss.h>
#include <blapit.h>
#include <pk11pub.h>
#include <hasht.h>
#include <prnetdb.h>
Expand All @@ -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
Expand All @@ -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;

Expand Down

0 comments on commit 52c5998

Please sign in to comment.