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