Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit edbc28db authored by Eric Biggers's avatar Eric Biggers Committed by Android (Google) Code Review
Browse files

Merge "Store output of SP800Derive in non-movable byte array" into main

parents 7f83cf75 119dcabc
Loading
Loading
Loading
Loading
+22 −3
Original line number Diff line number Diff line
@@ -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;

/**
@@ -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) {
@@ -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);
@@ -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);
    }

    /**
@@ -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);
        }
    }
}
+14 −0
Original line number Diff line number Diff line
@@ -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));
    }
}