content: /*
   * Copyright (C) 2015 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package android.security.keystore;
  
  import android.annotation.NonNull;
  import android.security.keymaster.KeymasterArguments;
  import android.security.keymaster.KeymasterDefs;
  
  import java.security.InvalidKeyException;
  import java.security.SignatureSpi;
  
  /**
   * Base class for {@link SignatureSpi} providing Android KeyStore backed RSA signatures.
   *
   * @hide
   */
  abstract class AndroidKeyStoreRSASignatureSpi extends AndroidKeyStoreSignatureSpiBase {
  
      abstract static class PKCS1Padding extends AndroidKeyStoreRSASignatureSpi {
          PKCS1Padding(int keymasterDigest) {
              super(keymasterDigest, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
          }
  
          @Override
          protected final int getAdditionalEntropyAmountForSign() {
              // No entropy required for this deterministic signature scheme.
              return 0;
          }
      }
  
      public static final class NONEWithPKCS1Padding extends PKCS1Padding {
          public NONEWithPKCS1Padding() {
              super(KeymasterDefs.KM_DIGEST_NONE);
          }
      }
  
      public static final class MD5WithPKCS1Padding extends PKCS1Padding {
          public MD5WithPKCS1Padding() {
              super(KeymasterDefs.KM_DIGEST_MD5);
          }
      }
  
      public static final class SHA1WithPKCS1Padding extends PKCS1Padding {
          public SHA1WithPKCS1Padding() {
              super(KeymasterDefs.KM_DIGEST_SHA1);
          }
      }
  
      public static final class SHA224WithPKCS1Padding extends PKCS1Padding {
          public SHA224WithPKCS1Padding() {
              super(KeymasterDefs.KM_DIGEST_SHA_2_224);
          }
      }
  
      public static final class SHA256WithPKCS1Padding extends PKCS1Padding {
          public SHA256WithPKCS1Padding() {
              super(KeymasterDefs.KM_DIGEST_SHA_2_256);
          }
      }
  
      public static final class SHA384WithPKCS1Padding extends PKCS1Padding {
          public SHA384WithPKCS1Padding() {
              super(KeymasterDefs.KM_DIGEST_SHA_2_384);
          }
      }
  
      public static final class SHA512WithPKCS1Padding extends PKCS1Padding {
          public SHA512WithPKCS1Padding() {
              super(KeymasterDefs.KM_DIGEST_SHA_2_512);
          }
      }
  
      abstract static class PSSPadding extends AndroidKeyStoreRSASignatureSpi {
          private static final int SALT_LENGTH_BYTES = 20;
  
          PSSPadding(int keymasterDigest) {
              super(keymasterDigest, KeymasterDefs.KM_PAD_RSA_PSS);
          }
  
          @Override
          protected final int getAdditionalEntropyAmountForSign() {
              return SALT_LENGTH_BYTES;
          }
      }
  
      public static final class SHA1WithPSSPadding extends PSSPadding {
          public SHA1WithPSSPadding() {
              super(KeymasterDefs.KM_DIGEST_SHA1);
          }
      }
  
      public static final class SHA224WithPSSPadding extends PSSPadding {
          public SHA224WithPSSPadding() {
              super(KeymasterDefs.KM_DIGEST_SHA_2_224);
          }
      }
  
      public static final class SHA256WithPSSPadding extends PSSPadding {
          public SHA256WithPSSPadding() {
              super(KeymasterDefs.KM_DIGEST_SHA_2_256);
          }
      }
  
      public static final class SHA384WithPSSPadding extends PSSPadding {
          public SHA384WithPSSPadding() {
              super(KeymasterDefs.KM_DIGEST_SHA_2_384);
          }
      }
  
      public static final class SHA512WithPSSPadding extends PSSPadding {
          public SHA512WithPSSPadding() {
              super(KeymasterDefs.KM_DIGEST_SHA_2_512);
          }
      }
  
      private final int mKeymasterDigest;
      private final int mKeymasterPadding;
  
      AndroidKeyStoreRSASignatureSpi(int keymasterDigest, int keymasterPadding) {
          mKeymasterDigest = keymasterDigest;
          mKeymasterPadding = keymasterPadding;
      }
  
      @Override
      protected final void initKey(AndroidKeyStoreKey key) throws InvalidKeyException {
          if (!KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(key.getAlgorithm())) {
              throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm()
                      + ". Only" + KeyProperties.KEY_ALGORITHM_RSA + " supported");
          }
          super.initKey(key);
      }
  
      @Override
      protected final void resetAll() {
          super.resetAll();
      }
  
      @Override
      protected final void resetWhilePreservingInitState() {
          super.resetWhilePreservingInitState();
      }
  
      @Override
      protected final void addAlgorithmSpecificParametersToBegin(
              @NonNull KeymasterArguments keymasterArgs) {
          keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
          keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
          keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
      }
  }
  