d8d41b5
# HG changeset patch
d8d41b5
# User Jack Magne <jmagne@redhat.com>
d8d41b5
# Date 1504307754 25200
d8d41b5
#      Fri Sep 01 16:15:54 2017 -0700
d8d41b5
# Node ID eec15518fd61f1d988c25b4de589555796f9e65f
d8d41b5
# Parent  17d1d7b740ca5777fbcf8ee817a2f26b9c93593a
d8d41b5
unwrapping of HMAC-SHA1 secret keys using AES wrapping and unwrapping
d8d41b5
cfu on behalf of jmagne
d8d41b5
d8d41b5
diff -r 17d1d7b740ca -r eec15518fd61 org/mozilla/jss/pkcs11/PK11KeyWrapper.java
d8d41b5
--- a/org/mozilla/jss/pkcs11/PK11KeyWrapper.java	Mon May 01 10:39:50 2017 -0700
d8d41b5
+++ b/org/mozilla/jss/pkcs11/PK11KeyWrapper.java	Fri Sep 01 16:15:54 2017 -0700
d8d41b5
@@ -588,6 +588,8 @@
d8d41b5
             return EncryptionAlgorithm.RC4;
d8d41b5
         } else if( type == SymmetricKey.AES ) {
d8d41b5
             return EncryptionAlgorithm.AES_128_ECB;
d8d41b5
+        } else if( type == SymmetricKey.SHA1_HMAC) {
d8d41b5
+            return HMACAlgorithm.SHA1;
d8d41b5
         } else  {
d8d41b5
             Assert._assert( type == SymmetricKey.RC2 );
d8d41b5
             return EncryptionAlgorithm.RC2_CBC;
d8d41b5
diff -r 17d1d7b740ca -r eec15518fd61 org/mozilla/jss/pkcs11/PK11MessageDigest.c
d8d41b5
--- a/org/mozilla/jss/pkcs11/PK11MessageDigest.c	Mon May 01 10:39:50 2017 -0700
d8d41b5
+++ b/org/mozilla/jss/pkcs11/PK11MessageDigest.c	Fri Sep 01 16:15:54 2017 -0700
d8d41b5
@@ -67,19 +67,19 @@
d8d41b5
     }
d8d41b5
 
d8d41b5
     /* copy the key, setting the CKA_SIGN attribute */
d8d41b5
-    /*
d8d41b5
+    
d8d41b5
     newKey = PK11_CopySymKeyForSigning(origKey, mech);
d8d41b5
+
d8d41b5
+    /* For some key on the hsm, this call could fail, but the key may work anyway */
d8d41b5
+
d8d41b5
     if( newKey == NULL ) {
d8d41b5
-        JSS_throwMsg(env, DIGEST_EXCEPTION,
d8d41b5
-                        "Unable to set CKA_SIGN attribute on symmetric key");
d8d41b5
-        goto finish;
d8d41b5
+        newKey = origKey;
d8d41b5
     }
d8d41b5
-    */
d8d41b5
 
d8d41b5
     param.data = NULL;
d8d41b5
     param.len = 0;
d8d41b5
 
d8d41b5
-    context = PK11_CreateContextBySymKey(mech, CKA_SIGN, origKey, ¶m;;
d8d41b5
+    context = PK11_CreateContextBySymKey(mech, CKA_SIGN, newKey, ¶m;;
d8d41b5
     if( context == NULL ) {
d8d41b5
         JSS_throwMsg(env, DIGEST_EXCEPTION,
d8d41b5
             "Unable to initialize digest context");
d8d41b5
@@ -88,7 +88,7 @@
d8d41b5
 
d8d41b5
     contextObj = JSS_PK11_wrapCipherContextProxy(env, &context);
d8d41b5
 finish:
d8d41b5
-    if(newKey) {
d8d41b5
+    if(newKey && (newKey != origKey)) {
d8d41b5
         /* SymKeys are ref counted, and the context will free it's ref
d8d41b5
          * when it is destroyed */
d8d41b5
         PK11_FreeSymKey(newKey);
d8d41b5
diff -r 17d1d7b740ca -r eec15518fd61 org/mozilla/jss/tests/HmacTest.java
d8d41b5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
d8d41b5
+++ b/org/mozilla/jss/tests/HmacTest.java	Fri Sep 01 16:15:54 2017 -0700
d8d41b5
@@ -0,0 +1,119 @@
d8d41b5
+
d8d41b5
+package org.mozilla.jss.tests;
d8d41b5
+
d8d41b5
+
d8d41b5
+import java.security.Key;
d8d41b5
+import javax.crypto.Cipher;
d8d41b5
+import javax.crypto.KeyGenerator;
d8d41b5
+import javax.crypto.Mac;
d8d41b5
+import javax.crypto.SecretKey;
d8d41b5
+import javax.crypto.spec.IvParameterSpec;
d8d41b5
+
d8d41b5
+import org.mozilla.jss.CryptoManager;
d8d41b5
+import org.mozilla.jss.crypto.CryptoToken;
d8d41b5
+import org.mozilla.jss.crypto.SymmetricKey;
d8d41b5
+
d8d41b5
+
d8d41b5
+public class HmacTest {
d8d41b5
+
d8d41b5
+  private static final String INTERNAL_KEY_STORAGE_TOKEN =
d8d41b5
+    new CryptoManager.InitializationValues("").getInternalKeyStorageTokenDescription().trim();
d8d41b5
+
d8d41b5
+  private static final String NSS_DATABASE_DIR = "sql:data";
d8d41b5
+  private static final String PROVIDER = "Mozilla-JSS";
d8d41b5
+
d8d41b5
+
d8d41b5
+  public static void main(String[] args)
d8d41b5
+   {
d8d41b5
+
d8d41b5
+    String algorithm = "hmac-sha1";
d8d41b5
+
d8d41b5
+    try {
d8d41b5
+       configureCrypto(args);
d8d41b5
+
d8d41b5
+       Mac mac = Mac.getInstance(algorithm, PROVIDER);
d8d41b5
+
d8d41b5
+       byte[] keyData = new byte[16];
d8d41b5
+       Key key = importHmacSha1Key(keyData);
d8d41b5
+
d8d41b5
+       mac.init(key);
d8d41b5
+
d8d41b5
+       doHMAC(mac,"Dogtag rules!");
d8d41b5
+
d8d41b5
+       System.out.println("Done");
d8d41b5
+
d8d41b5
+       System.exit(0);
d8d41b5
+    } catch (Exception e) {
d8d41b5
+        System.exit(1);
d8d41b5
+    }
d8d41b5
+  }
d8d41b5
+
d8d41b5
+  private static void configureCrypto(String[] args)
d8d41b5
+    throws Exception {
d8d41b5
+
d8d41b5
+    CryptoManager.InitializationValues initializationValues =
d8d41b5
+      new CryptoManager.InitializationValues(args[0]);
d8d41b5
+
d8d41b5
+    CryptoManager.initialize(initializationValues);
d8d41b5
+
d8d41b5
+    CryptoManager cryptoManager = CryptoManager.getInstance();
d8d41b5
+
d8d41b5
+    CryptoToken cryptoToken =
d8d41b5
+      cryptoManager.getTokenByName(INTERNAL_KEY_STORAGE_TOKEN);
d8d41b5
+
d8d41b5
+    cryptoManager.setThreadToken(cryptoToken);
d8d41b5
+  }
d8d41b5
+
d8d41b5
+  private static Key importHmacSha1Key(byte[] key)
d8d41b5
+    throws Exception {
d8d41b5
+
d8d41b5
+    final String WRAPPING_ALGORITHM = "AES/CBC/PKCS5Padding";
d8d41b5
+
d8d41b5
+    Key wrappingKey = getWrappingKey();
d8d41b5
+
d8d41b5
+    byte[] iv = new byte[16];
d8d41b5
+    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
d8d41b5
+
d8d41b5
+    Cipher wrappingCipher = Cipher.getInstance(WRAPPING_ALGORITHM, PROVIDER);
d8d41b5
+    wrappingCipher.init(Cipher.ENCRYPT_MODE, wrappingKey, ivParameterSpec);
d8d41b5
+
d8d41b5
+    byte[] wrappedKeyData = wrappingCipher.doFinal(key);
d8d41b5
+
d8d41b5
+    Cipher unwrappingCipher = Cipher.getInstance(WRAPPING_ALGORITHM, PROVIDER);
d8d41b5
+    unwrappingCipher.init(Cipher.UNWRAP_MODE, wrappingKey, ivParameterSpec);
d8d41b5
+
d8d41b5
+    return (SecretKey) unwrappingCipher.unwrap(wrappedKeyData,
d8d41b5
+                                               SymmetricKey.SHA1_HMAC.toString(),
d8d41b5
+                                               Cipher.SECRET_KEY);
d8d41b5
+  }
d8d41b5
+
d8d41b5
+  private static synchronized Key getWrappingKey()
d8d41b5
+    throws Exception {
d8d41b5
+
d8d41b5
+    final String keyGenAlgorithm = "AES";
d8d41b5
+    final int wrappingKeyLength = 256;
d8d41b5
+
d8d41b5
+    KeyGenerator keyGen = KeyGenerator.getInstance(keyGenAlgorithm, PROVIDER);
d8d41b5
+    keyGen.init(wrappingKeyLength);
d8d41b5
+    return keyGen.generateKey();
d8d41b5
+  }
d8d41b5
+
d8d41b5
+  public static void doHMAC(Mac mozillaHmac, String clearText)
d8d41b5
+            throws Exception {
d8d41b5
+        byte[] mozillaHmacOut;
d8d41b5
+
d8d41b5
+        //Get the Mozilla HMAC
d8d41b5
+        mozillaHmacOut = mozillaHmac.doFinal(clearText.getBytes());
d8d41b5
+
d8d41b5
+        if (mozillaHmacOut.length == mozillaHmac.getMacLength()) {
d8d41b5
+            System.out.println(PROVIDER + " supports " +
d8d41b5
+                    mozillaHmac.getAlgorithm() + "  and the output size is " + mozillaHmac.getMacLength());
d8d41b5
+        } else {
d8d41b5
+            throw new Exception("ERROR: hmac output size is " +
d8d41b5
+                    mozillaHmacOut.length + ", should be " +
d8d41b5
+                    mozillaHmac.getMacLength());
d8d41b5
+        }
d8d41b5
+    }
d8d41b5
+
d8d41b5
+
d8d41b5
+}
d8d41b5
diff -r 17d1d7b740ca -r eec15518fd61 org/mozilla/jss/tests/all.pl
d8d41b5
--- a/org/mozilla/jss/tests/all.pl	Mon May 01 10:39:50 2017 -0700
d8d41b5
+++ b/org/mozilla/jss/tests/all.pl	Fri Sep 01 16:15:54 2017 -0700
d8d41b5
@@ -492,6 +492,10 @@
d8d41b5
 $command = "$java -cp $jss_classpath org.mozilla.jss.tests.HMACTest $testdir $pwfile";
d8d41b5
 run_test($testname, $command);
d8d41b5
 
d8d41b5
+$testname = "HMAC Unwrap";
d8d41b5
+$command = "$java -cp $jss_classpath org.mozilla.jss.tests.HmacTest $testdir $pwfile";
d8d41b5
+run_test($testname, $command);
d8d41b5
+
d8d41b5
 $testname = "KeyWrapping ";
d8d41b5
 $command = "$java -cp $jss_classpath org.mozilla.jss.tests.JCAKeyWrap $testdir $pwfile";
d8d41b5
 run_test($testname, $command);