Loading services/core/java/com/android/server/locksettings/SP800Derive.java +22 −3 Original line number Diff line number Diff line Loading @@ -16,11 +16,14 @@ package com.android.server.locksettings; import com.android.internal.util.ArrayUtils; import java.nio.ByteBuffer; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.Mac; import javax.crypto.ShortBufferException; import javax.crypto.spec.SecretKeySpec; /** Loading @@ -34,6 +37,8 @@ import javax.crypto.spec.SecretKeySpec; * L suffix: 32 bits */ class SP800Derive { private static final int OUTPUT_LENGTH = 32; // length of output in bytes private final byte[] mKeyBytes; SP800Derive(byte[] keyBytes) { Loading @@ -44,6 +49,9 @@ class SP800Derive { try { final Mac m = Mac.getInstance("HmacSHA256"); m.init(new SecretKeySpec(mKeyBytes, m.getAlgorithm())); if (m.getMacLength() != OUTPUT_LENGTH) { throw new IllegalStateException("Wrong output length"); } return m; } catch (InvalidKeyException | NoSuchAlgorithmException e) { throw new RuntimeException(e); Loading @@ -61,7 +69,7 @@ class SP800Derive { final Mac m = getMac(); update32(m, 1); // Hardwired counter value m.update(fixedInput); return m.doFinal(); return doFinal(m); } /** Loading @@ -76,7 +84,18 @@ class SP800Derive { m.update((byte) 0); m.update(context); update32(m, context.length * 8); // Disambiguate context update32(m, 256); // Hardwired output length return m.doFinal(); update32(m, OUTPUT_LENGTH * 8); // Hardwired output length return doFinal(m); } // Same as m.doFinal(), but returns the output in a non-movable byte array. private byte[] doFinal(Mac m) { final byte[] mac = ArrayUtils.newNonMovableByteArray(OUTPUT_LENGTH); try { m.doFinal(mac, 0); return mac; } catch (ShortBufferException e) { throw new RuntimeException(e); } } } services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java +14 −0 Original line number Diff line number Diff line Loading @@ -49,4 +49,18 @@ public class SP800DeriveTests { "770dfab6a6a4a4bee0257ff335213f78" + "d8287b4fd537d5c1fffa956910e7c779").toUpperCase(), HexDump.toHexString(res)); } @Test public void testWithContext() throws Exception { byte[] keyBytes = HexDump.hexStringToByteArray( "e204d6d466aad507ffaf6d6dab0a5b26" + "152c9e21e764370464e360c8fbc765c6"); SP800Derive sk = new SP800Derive(keyBytes); byte[] label = HexDump.hexStringToByteArray("ed8282442dbfe03aaa1799faa5"); byte[] context = HexDump.hexStringToByteArray("6c0b857412ef52"); byte[] res = sk.withContext(label, context); assertEquals(( "21658822e750a33d9ed743627697f0ea" + "12543b5edef19cc453f01da949e5e37f").toUpperCase(), HexDump.toHexString(res)); } } Loading
services/core/java/com/android/server/locksettings/SP800Derive.java +22 −3 Original line number Diff line number Diff line Loading @@ -16,11 +16,14 @@ package com.android.server.locksettings; import com.android.internal.util.ArrayUtils; import java.nio.ByteBuffer; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.Mac; import javax.crypto.ShortBufferException; import javax.crypto.spec.SecretKeySpec; /** Loading @@ -34,6 +37,8 @@ import javax.crypto.spec.SecretKeySpec; * L suffix: 32 bits */ class SP800Derive { private static final int OUTPUT_LENGTH = 32; // length of output in bytes private final byte[] mKeyBytes; SP800Derive(byte[] keyBytes) { Loading @@ -44,6 +49,9 @@ class SP800Derive { try { final Mac m = Mac.getInstance("HmacSHA256"); m.init(new SecretKeySpec(mKeyBytes, m.getAlgorithm())); if (m.getMacLength() != OUTPUT_LENGTH) { throw new IllegalStateException("Wrong output length"); } return m; } catch (InvalidKeyException | NoSuchAlgorithmException e) { throw new RuntimeException(e); Loading @@ -61,7 +69,7 @@ class SP800Derive { final Mac m = getMac(); update32(m, 1); // Hardwired counter value m.update(fixedInput); return m.doFinal(); return doFinal(m); } /** Loading @@ -76,7 +84,18 @@ class SP800Derive { m.update((byte) 0); m.update(context); update32(m, context.length * 8); // Disambiguate context update32(m, 256); // Hardwired output length return m.doFinal(); update32(m, OUTPUT_LENGTH * 8); // Hardwired output length return doFinal(m); } // Same as m.doFinal(), but returns the output in a non-movable byte array. private byte[] doFinal(Mac m) { final byte[] mac = ArrayUtils.newNonMovableByteArray(OUTPUT_LENGTH); try { m.doFinal(mac, 0); return mac; } catch (ShortBufferException e) { throw new RuntimeException(e); } } }
services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java +14 −0 Original line number Diff line number Diff line Loading @@ -49,4 +49,18 @@ public class SP800DeriveTests { "770dfab6a6a4a4bee0257ff335213f78" + "d8287b4fd537d5c1fffa956910e7c779").toUpperCase(), HexDump.toHexString(res)); } @Test public void testWithContext() throws Exception { byte[] keyBytes = HexDump.hexStringToByteArray( "e204d6d466aad507ffaf6d6dab0a5b26" + "152c9e21e764370464e360c8fbc765c6"); SP800Derive sk = new SP800Derive(keyBytes); byte[] label = HexDump.hexStringToByteArray("ed8282442dbfe03aaa1799faa5"); byte[] context = HexDump.hexStringToByteArray("6c0b857412ef52"); byte[] res = sk.withContext(label, context); assertEquals(( "21658822e750a33d9ed743627697f0ea" + "12543b5edef19cc453f01da949e5e37f").toUpperCase(), HexDump.toHexString(res)); } }