|
41 | 41 | import java.security.KeyStoreSpi; |
42 | 42 | import java.security.NoSuchAlgorithmException; |
43 | 43 | import java.security.PrivateKey; |
| 44 | +import java.security.ProviderException; |
44 | 45 | import java.security.PublicKey; |
45 | 46 | import java.security.UnrecoverableKeyException; |
46 | 47 | import java.security.cert.Certificate; |
@@ -605,50 +606,43 @@ private void setSecretKeyEntry(String entryAlias, SecretKey key, |
605 | 606 | args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm); |
606 | 607 |
|
607 | 608 | int[] keymasterDigests; |
608 | | - int keymasterDigest = KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm()); |
609 | | - if (params.isDigestsSpecified()) { |
610 | | - // Digest(s) specified in parameters |
611 | | - keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests()); |
612 | | - if (keymasterDigest != -1) { |
613 | | - // Digest also specified in the JCA key algorithm name. |
614 | | - if (!com.android.internal.util.ArrayUtils.contains( |
615 | | - keymasterDigests, keymasterDigest)) { |
616 | | - throw new KeyStoreException("Digest specified in key algorithm " |
617 | | - + key.getAlgorithm() + " not specified in protection parameters: " |
618 | | - + Arrays.asList(params.getDigests())); |
619 | | - } |
620 | | - // When the key is read back from keystore we reconstruct the JCA key algorithm |
621 | | - // name from the KM_TAG_ALGORITHM and the first KM_TAG_DIGEST. Thus we need to |
622 | | - // ensure that the digest reflected in the JCA key algorithm name is the first |
623 | | - // KM_TAG_DIGEST tag. |
624 | | - if (keymasterDigests[0] != keymasterDigest) { |
625 | | - // The first digest is not the one implied by the JCA key algorithm name. |
626 | | - // Swap the implied digest with the first one. |
627 | | - for (int i = 0; i < keymasterDigests.length; i++) { |
628 | | - if (keymasterDigests[i] == keymasterDigest) { |
629 | | - keymasterDigests[i] = keymasterDigests[0]; |
630 | | - keymasterDigests[0] = keymasterDigest; |
631 | | - break; |
632 | | - } |
633 | | - } |
| 609 | + if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) { |
| 610 | + // JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm |
| 611 | + // implies SHA-256 digest). Because keymaster HMAC key is authorized only for one |
| 612 | + // digest, we don't let import parameters override the digest implied by the key. |
| 613 | + // If the parameters specify digests at all, they must specify only one digest, the |
| 614 | + // only implied by key algorithm. |
| 615 | + int keymasterImpliedDigest = |
| 616 | + KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm()); |
| 617 | + if (keymasterImpliedDigest == -1) { |
| 618 | + throw new ProviderException( |
| 619 | + "HMAC key algorithm digest unknown for key algorithm " |
| 620 | + + key.getAlgorithm()); |
| 621 | + } |
| 622 | + keymasterDigests = new int[] {keymasterImpliedDigest}; |
| 623 | + if (params.isDigestsSpecified()) { |
| 624 | + // Digest(s) explicitly specified in params -- check that the list consists of |
| 625 | + // exactly one digest, the one implied by key algorithm. |
| 626 | + int[] keymasterDigestsFromParams = |
| 627 | + KeyProperties.Digest.allToKeymaster(params.getDigests()); |
| 628 | + if ((keymasterDigestsFromParams.length != 1) |
| 629 | + || (keymasterDigestsFromParams[0] != keymasterImpliedDigest)) { |
| 630 | + throw new KeyStoreException( |
| 631 | + "Unsupported digests specification: " |
| 632 | + + Arrays.asList(params.getDigests()) + ". Only " |
| 633 | + + KeyProperties.Digest.fromKeymaster(keymasterImpliedDigest) |
| 634 | + + " supported for HMAC key algorithm " + key.getAlgorithm()); |
634 | 635 | } |
635 | 636 | } |
636 | 637 | } else { |
637 | | - // No digest specified in parameters |
638 | | - if (keymasterDigest != -1) { |
639 | | - // Digest specified in the JCA key algorithm name. |
640 | | - keymasterDigests = new int[] {keymasterDigest}; |
| 638 | + // Key algorithm does not imply a digest. |
| 639 | + if (params.isDigestsSpecified()) { |
| 640 | + keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests()); |
641 | 641 | } else { |
642 | 642 | keymasterDigests = EmptyArray.INT; |
643 | 643 | } |
644 | 644 | } |
645 | 645 | args.addEnums(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests); |
646 | | - if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) { |
647 | | - if (keymasterDigests.length == 0) { |
648 | | - throw new KeyStoreException("At least one digest algorithm must be specified" |
649 | | - + " for key algorithm " + key.getAlgorithm()); |
650 | | - } |
651 | | - } |
652 | 646 |
|
653 | 647 | @KeyProperties.PurposeEnum int purposes = params.getPurposes(); |
654 | 648 | int[] keymasterBlockModes = |
|
0 commit comments