diff --git a/fido/src/main/java/com/yubico/yubikit/fido/ctap/Hkdf.java b/fido/src/main/java/com/yubico/yubikit/fido/ctap/Hkdf.java index 6e33e6b7..b75f2ff7 100644 --- a/fido/src/main/java/com/yubico/yubikit/fido/ctap/Hkdf.java +++ b/fido/src/main/java/com/yubico/yubikit/fido/ctap/Hkdf.java @@ -61,20 +61,29 @@ byte[] expand(byte[] prk, byte[] info, int length) throws InvalidKeyException { .put(info) .put(i) .array(); - t = hmacDigest(prk, data); + Arrays.fill(t, (byte) 0); + byte[] digest = hmacDigest(prk, data); - okm = ByteBuffer.allocate(okm.length + t.length) + byte[] result = ByteBuffer.allocate(okm.length + digest.length) .put(okm) - .put(t) + .put(digest) .array(); + Arrays.fill(okm, (byte) 0); + Arrays.fill(data, (byte) 0); + okm = result; + t = digest; } - return Arrays.copyOf(okm, length); + byte[] result = Arrays.copyOf(okm, length); + Arrays.fill(okm, (byte) 0); + return result; } byte[] digest(byte[] ikm, byte[] salt, byte[] info, int length) throws NoSuchAlgorithmException, InvalidKeyException { byte[] prk = extract(salt, ikm); - return expand(prk, info, length); + byte[] result = expand(prk, info, length); + Arrays.fill(prk, (byte) 0); + return result; } } diff --git a/fido/src/main/java/com/yubico/yubikit/fido/ctap/PinUvAuthProtocolV2.java b/fido/src/main/java/com/yubico/yubikit/fido/ctap/PinUvAuthProtocolV2.java index a6cd0b3a..d35b3ac9 100644 --- a/fido/src/main/java/com/yubico/yubikit/fido/ctap/PinUvAuthProtocolV2.java +++ b/fido/src/main/java/com/yubico/yubikit/fido/ctap/PinUvAuthProtocolV2.java @@ -56,14 +56,16 @@ public int getVersion() { @Override public byte[] kdf(byte[] z) { + byte[] hmacKey = null; + byte[] aesKey = null; try { - byte[] hmacKey = new Hkdf(HKDF_ALG).digest( + hmacKey = new Hkdf(HKDF_ALG).digest( z, HKDF_SALT, HKDF_INFO_HMAC, HKDF_LENGTH); - byte[] aesKey = new Hkdf(HKDF_ALG).digest( + aesKey = new Hkdf(HKDF_ALG).digest( z, HKDF_SALT, HKDF_INFO_AES, @@ -75,13 +77,21 @@ public byte[] kdf(byte[] z) { .array(); } catch (NoSuchAlgorithmException | InvalidKeyException e) { throw new IllegalStateException(e); + } finally { + if (hmacKey != null) { + Arrays.fill(hmacKey, (byte) 0); + } + if (aesKey != null) { + Arrays.fill(aesKey, (byte) 0); + } } } @Override public byte[] encrypt(byte[] key, byte[] plaintext) { + byte[] aesKey = null; try { - byte[] aesKey = Arrays.copyOfRange(key, 32, key.length); + aesKey = Arrays.copyOfRange(key, 32, key.length); byte[] iv = RandomUtils.getRandomBytes(16); final byte[] ciphertext = @@ -93,19 +103,27 @@ public byte[] encrypt(byte[] key, byte[] plaintext) { .array(); } catch (IllegalBlockSizeException | BadPaddingException e) { throw new IllegalStateException(e); + } finally { + if (aesKey != null) { + Arrays.fill(aesKey, (byte) 0); + } } } @Override public byte[] decrypt(byte[] key, byte[] ciphertext) { + byte[] aesKey = null; try { - byte[] aesKey = Arrays.copyOfRange(key, 32, key.length); + aesKey = Arrays.copyOfRange(key, 32, key.length); byte[] iv = Arrays.copyOf(ciphertext, 16); byte[] ct = Arrays.copyOfRange(ciphertext, 16, ciphertext.length); - byte[] plaintext = getCipher(Cipher.DECRYPT_MODE, aesKey, iv).doFinal(ct); - return Arrays.copyOf(plaintext, plaintext.length); + return getCipher(Cipher.DECRYPT_MODE, aesKey, iv).doFinal(ct); } catch (BadPaddingException | IllegalBlockSizeException e) { throw new IllegalStateException(e); + } finally { + if (aesKey != null) { + Arrays.fill(aesKey, (byte) 0); + } } } @@ -120,8 +138,7 @@ public byte[] authenticate(byte[] key, byte[] message) { } catch (NoSuchAlgorithmException | InvalidKeyException e) { throw new RuntimeException(e); } - byte[] result = mac.doFinal(message); - return Arrays.copyOf(result, result.length); + return mac.doFinal(message); } private Cipher getCipher(int mode, byte[] secret, byte[] iv) {