All Downloads are FREE. Search and download functionalities are using the official Maven repository.

iaik.pkcs.pkcs11.wrapper.Functions Maven / Gradle / Ivy

The newest version!
// Copyright (c) 2002 Graz University of Technology. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. The end-user documentation included with the redistribution, if any, must
//    include the following acknowledgment:
//
//    "This product includes software developed by IAIK of Graz University of
//     Technology."
//
//    Alternately, this acknowledgment may appear in the software itself, if and
//    wherever such third-party acknowledgments normally appear.
//
// 4. The names "Graz University of Technology" and "IAIK of Graz University of
//    Technology" must not be used to endorse or promote products derived from
//    this software without prior written permission.
//
// 5. Products derived from this software may not be called "IAIK PKCS Wrapper",
//    nor may "IAIK" appear in their name, without prior written permission of
//    Graz University of Technology.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

package iaik.pkcs.pkcs11.wrapper;

import iaik.pkcs.pkcs11.Mechanism;

import java.util.*;

/**
 * This class contains only static methods. It is the place for all functions
 * that are used by several classes in this package.
 *
 * @author Karl Scheibelhofer
 * @author Martin Schlaeffer
 * @author Lijun Liao
 */
public class Functions implements PKCS11Constants {

  private static class Hex {

    private static final char[] DIGITS = {'0', '1', '2', '3', '4',
        '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    private static final char[] UPPER_DIGITS = {'0', '1', '2', '3', '4',
        '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    private static final int[] LINTS = new int['f' + 1];
    private static final int[] HINTS = new int[LINTS.length];

    static {
      for (int i = 0; i < DIGITS.length; i++) {
        LINTS[DIGITS[i]] = i;
      }

      for (int i = 10; i < UPPER_DIGITS.length; i++) {
        LINTS[UPPER_DIGITS[i]] = i;
      }

      for (int i = 0; i < LINTS.length; i++) {
        HINTS[i] = LINTS[i] << 4;
      }
    }

    public static String encode(byte[] bytes) {
      return new String(encodeToChars(bytes));
    }

    public static char[] encodeToChars(byte[] data) {
      int len = data.length;

      char[] out = new char[len << 1];

      // two characters form the hex value.
      for (int i = 0, j = 0; i < len; i++) {
        out[j++] = DIGITS[(0xF0 & data[i]) >>> 4];
        out[j++] = DIGITS[0x0F & data[i]];
      }

      return out;
    }

    public static byte[] decode(String hex) {
      char[] data = hex.toCharArray();
      int len = data.length;

      if ((len & 0x01) != 0) {
        throw new IllegalArgumentException("Odd number of characters.");
      }

      byte[] out = new byte[len >> 1];

      // two characters form the hex value.
      for (int i = 0, j = 0; j < len; i++) {
        out[i] = (byte) (HINTS[data[j++]] | LINTS[data[j++]]);
      }

      return out;
    }

  }

  /**
   * The name of the properties file that holds the names of the PKCS#11
   * mechanism-codes.
   */
  private static final String CKM_CODE_PROPERTIES
      = "/iaik/pkcs/pkcs11/wrapper/ckm.properties";

  /**
   * The name of the properties file that holds the names of the PKCS#11
   * mechanism-codes.
   */
  private static final String CKR_CODE_PROPERTIES
      = "/iaik/pkcs/pkcs11/wrapper/ckr.properties";

  /**
   * True, if the mapping of mechanism codes to PKCS#11 mechanism names is
   * available.
   */
  private static boolean mechCodeNamesAvailable;

  /**
   * Maps mechanism codes as Long to their names as Strings.
   */
  private static Map mechNames;

  /**
   * Maps mechanism name as String to their code as Long.
   */
  private static Map mechNameToCodes;

  private static final Map hashMechCodeToHashNames;

  /**
   * True, if the mapping of error codes to PKCS#11 error names is available.
   */
  private static boolean errorCodeNamesAvailable;

  /**
   * The properties object that holds the mapping from error-code to the name
   * of the PKCS#11 error.
   */
  private static Map errorCodeNames;

  // MGFs (CKG_*)
  private static final Map mgfNames = new HashMap<>();

  /**
   * This set contains the mechanisms that are full encrypt/decrypt
   * mechanisms; i.e. mechanisms that support the update functions.
   */
  private static Set fullEncryptDecryptMechs;

  /**
   * This set contains the mechanisms that are single-operation
   * encrypt/decrypt mechanisms; i.e. mechanisms that do not support the
   * update functions.
   */
  private static Set sglOpEncryptDecryptMechs;

  /**
   * This set contains the mechanisms that are full sign/verify
   * mechanisms; i.e. mechanisms that support the update functions.
   */
  private static Set fullSignVerifyMechs;

  /**
   * This set contains the mechanisms that are single-operation
   * sign/verify mechanisms; i.e. mechanisms that do not support the update
   * functions.
   */
  private static Set sglOpSignVerifyMechs;

  /**
   * This table contains the mechanisms that are sign/verify mechanisms with
   * message recovery.
   */
  private static Set signVerifyRecoverMechs;

  /**
   * This set contains the mechanisms that are digest mechanisms.
   * The Long values of the mechanisms are the keys, and the mechanism
   * names are the values.
   */
  private static Set digestMechs;

  /**
   * This table contains the mechanisms that key generation mechanisms; i.e.
   * mechanisms for generating symmetric keys.
   */
  private static Set keyGenMechs;

  /**
   * This table contains the mechanisms that key-pair generation mechanisms;
   * i.e. mechanisms for generating key-pairs.
   */
  private static Set keyPairGenMechs;

  /**
   * This table contains the mechanisms that are wrap/unwrap mechanisms.
   */
  private static Set wrapUnwrapMechs;

  /**
   * This table contains the mechanisms that are key derivation mechanisms.
   */
  private static Set keyDerivationMechs;

  static {
    hashMechCodeToHashNames = new HashMap<>();
    hashMechCodeToHashNames.put(CKM_SHA_1,      "SHA1");
    hashMechCodeToHashNames.put(CKM_SHA224,     "SHA224");
    hashMechCodeToHashNames.put(CKM_SHA256,     "SHA256");
    hashMechCodeToHashNames.put(CKM_SHA384,     "SHA384");
    hashMechCodeToHashNames.put(CKM_SHA512,     "SHA512");
    hashMechCodeToHashNames.put(CKM_SHA512_224, "SHA512/224");
    hashMechCodeToHashNames.put(CKM_SHA512_256, "SHA512/256");
    hashMechCodeToHashNames.put(CKM_SHA3_224,   "SHA3-224");
    hashMechCodeToHashNames.put(CKM_SHA3_256,   "SHA3-256");
    hashMechCodeToHashNames.put(CKM_SHA3_384,   "SHA3-384");
    hashMechCodeToHashNames.put(CKM_SHA3_512,   "SHA3-512");

    mgfNames.put(CKG_MGF1_SHA1,     "CKG_MGF1_SHA1");
    mgfNames.put(CKG_MGF1_SHA256,   "CKG_MGF1_SHA256");
    mgfNames.put(CKG_MGF1_SHA384,   "CKG_MGF1_SHA384");
    mgfNames.put(CKG_MGF1_SHA512,   "CKG_MGF1_SHA512");
    mgfNames.put(CKG_MGF1_SHA224,   "CKG_MGF1_SHA224");
    mgfNames.put(CKG_MGF1_SHA3_224, "CKG_MGF1_SHA3-224");
    mgfNames.put(CKG_MGF1_SHA3_256, "CKG_MGF1_SHA3-256");
    mgfNames.put(CKG_MGF1_SHA3_384, "CKG_MGF1_SHA3-384");
    mgfNames.put(CKG_MGF1_SHA3_512, "CKG_MGF1_SHA3-512");
  }

  /**
   * Converts the long value code of a mechanism to a name.
   *
   * @param mechCode
   *          The code of the mechanism to be converted to a string.
   * @return The string representation of the mechanism.
   */
  public static String mechanismCodeToString(long mechCode) {
    initMechanismMap();
    String name = mechCodeNamesAvailable ? mechNames.get(mechCode) : null;

    if (name == null) {
      name = "Unknown mechanism with code: 0x" + toFullHex(mechCode);
    }

    return name;
  }

  /**
   * Describes the mechanism in form of <hex digital>(name), like
   * 0x00001082 (CKM_AES_CBC).
   *
   * @param mechCode
   *          The code of the mechanism to be converted to a string.
   * @return The description of the mechanism.
   */
  public static String getMechanismDescription(long mechCode) {
    StringBuilder sb = new StringBuilder();
    sb.append(String.format("%#010x", mechCode));
    String name = mechanismCodeToString(mechCode);
    sb.append(" (").append(name).append(")");
    return sb.toString();
  }

  /**
   * Converts the mechanism name to code value.
   *
   * @param mechName
   *          The name of the mechanism to be converted to a code.
   * @return The code representation of the mechanism.
   */
  public static long mechanismStringToCode(String mechName) {
    initMechanismMap();
    Long code = mechCodeNamesAvailable
        ? mechNameToCodes.get(mechName) : null;
    return (code != null) ? code : -1;
  }

  public static String getMGFName(long id) {
    return mgfNames.get(id);
  }

  private static synchronized void initMechanismMap() {
    // ensure that another thread has not loaded the codes meanwhile
    if (mechNames != null) {
      return;
    }

    // if the names of the defined codes are not yet loaded, load them
    Map codeNameMap = new HashMap<>();
    Map nameCodeMap = new HashMap<>();

    Properties props = new Properties();
    try {
      props.load(Functions.class.getResourceAsStream(CKM_CODE_PROPERTIES));
      for (String propName : props.stringPropertyNames()) {
        String mechNames = props.getProperty(propName);
        StringTokenizer tokens = new StringTokenizer(mechNames, ",");

        if (!tokens.hasMoreTokens()) {
          System.out.println(
              "No name defined for Mechanism code " + propName);
        }

        long code;
        if (propName.startsWith("0x") || propName.startsWith("0X")) {
          code = Long.parseLong(propName.substring(2), 16);
        } else {
          code = Long.parseLong(propName);
        }

        String mainMechName = tokens.nextToken();
        codeNameMap.put(code, mainMechName);

        while (tokens.hasMoreTokens()) {
          nameCodeMap.put(tokens.nextToken(), code);
        }
      }

      codeNameMap.put(CKM_VENDOR_ISO2_SM4_MAC, "CKM_VENDOR_ISO2_SM4_MAC");
      codeNameMap.put(CKM_VENDOR_ISO2_SM4_MAC_GENERAL,
          "CKM_VENDOR_ISO2_SM4_MAC_GENERAL");
      codeNameMap.put(CKM_VENDOR_SM2, "CKM_VENDOR_SM2");
      codeNameMap.put(CKM_VENDOR_SM2_ENCRYPT, "CKM_VENDOR_SM2_ENCRYPT");
      codeNameMap.put(CKM_VENDOR_SM2_KEY_PAIR_GEN,
          "CKM_VENDOR_SM2_KEY_PAIR_GEN");
      codeNameMap.put(CKM_VENDOR_SM2_SM3, "CKM_VENDOR_SM2_SM3");
      codeNameMap.put(CKM_VENDOR_SM3, "CKM_VENDOR_SM3");
      codeNameMap.put(CKM_VENDOR_SM4_CBC, "CKM_VENDOR_SM4_CBC");
      codeNameMap.put(CKM_VENDOR_SM4_ECB, "CKM_VENDOR_SM4_ECB");
      codeNameMap.put(CKM_VENDOR_SM4_ECB_ENCRYPT_DATA,
          "CKM_VENDOR_SM4_ECB_ENCRYPT_DATA");
      codeNameMap.put(CKM_VENDOR_SM4_KEY_GEN, "CKM_VENDOR_SM4_KEY_GEN");
      codeNameMap.put(CKM_VENDOR_SM4_MAC, "CKM_VENDOR_SM4_MAC");
      codeNameMap.put(CKM_VENDOR_SM4_MAC_GENERAL, "CKM_VENDOR_SM4_MAC_GENERAL");

      Set codes = codeNameMap.keySet();
      for (Long code : codes) {
        nameCodeMap.put(codeNameMap.get(code), code);
      }

      mechNames = codeNameMap;
      mechNameToCodes = nameCodeMap;
      mechCodeNamesAvailable = true;
    } catch (Exception ex) {
      System.err.println(
          "Could not read properties for code names: " + ex.getMessage());
    }
  }

  /**
   * Converts the long value code of an error to a name.
   *
   * @param errorCode
   *          The code of the error to be converted to a string.
   * @return The string representation of the error.
   */
  public static String errorCodeToString(long errorCode) {
    initErrorCodeMap();

    String name = errorCodeNamesAvailable
        ? errorCodeNames.get(errorCode) : null;
    if (name == null) {
      name = "Unknown CKR with code: 0x" + toFullHex(errorCode);
    }

    return name;
  }

  private static synchronized void initErrorCodeMap() {
    // ensure that another thread has not loaded the codes meanwhile
    if (errorCodeNames != null) {
      return;
    }

    // if the names of the defined codes are not yet loaded, load them
    Map codeNamMap = new HashMap<>();
    Properties props = new Properties();
    try {
      props.load(Functions.class.getResourceAsStream(CKR_CODE_PROPERTIES));
      for (String propName : props.stringPropertyNames()) {
        String errorName = props.getProperty(propName);
        long code;
        if (propName.startsWith("0x") || propName.startsWith("0X")) {
          code = Long.parseLong(propName.substring(2), 16);
        } else {
          code = Long.parseLong(propName);
        }
        codeNamMap.put(code, errorName);
      }
      errorCodeNames = codeNamMap;
      errorCodeNamesAvailable = true;
    } catch (Exception ex) {
      System.err.println("Could not read properties for error code names: "
          + ex.getMessage());
    }
  }

  private static Set asSet(long[] elements) {
    HashSet set = new HashSet<>();
    for (long el : elements) {
      set.add(el);
    }
    return set;
  }

  /**
   * This method checks, if the mechanism with the given code is a full
   * encrypt/decrypt mechanism; i.e. it supports the encryptUpdate() and
   * decryptUpdate() functions.
   * If Returns true, the mechanism can be used with the encrypt
   * and decrypt functions including encryptUpdate and decryptUpdate.
   *
   * @param mechCode
   *          The code of the mechanism to check.
   * @return True, if the provided mechanism is a full encrypt/decrypt
   *         mechanism. False, otherwise.
   */
  public static boolean isFullEncryptDecryptMechanism(long mechCode) {
    // build the hashtable on demand (=first use)
    if (fullEncryptDecryptMechs == null) {
      long[] mechs = new long[]{
        CKM_AES_ECB,
        CKM_AES_CBC,
        CKM_AES_CBC_PAD,
        CKM_AES_OFB,
        CKM_AES_CFB64,
        CKM_AES_CFB8,
        CKM_AES_CFB128,
        CKM_AES_CFB1,
        CKM_AES_XTS,
        CKM_AES_CTR,
        CKM_AES_CTS,
        CKM_AES_GCM,
        CKM_AES_CCM,
        CKM_AES_KEY_WRAP,
        CKM_AES_KEY_WRAP_PAD,
        CKM_AES_KEY_WRAP_KWP,
        CKM_DES3_ECB,
        CKM_DES3_CBC,
        CKM_DES3_CBC_PAD,
        CKM_DES_OFB64,
        CKM_DES_OFB8,
        CKM_DES_CFB64,
        CKM_DES_CFB8,
        CKM_BLOWFISH_CBC,
        CKM_BLOWFISH_CBC_PAD,
        CKM_CAMELLIA_ECB,
        CKM_CAMELLIA_CBC,
        CKM_CAMELLIA_CBC_PAD,
        CKM_ARIA_ECB,
        CKM_ARIA_CBC,
        CKM_ARIA_CBC_PAD,
        CKM_SEED_CBC_PAD,
        CKM_GOST28147_ECB,
        CKM_GOST28147,
        CKM_CHACHA20,
        CKM_SALSA20,
        CKM_CHACHA20_POLY1305,
        CKM_SALSA20_POLY1305,
        CKM_X2RATCHET_ENCRYPT,
        CKM_X2RATCHET_DECRYPT,
        // Vendor Mechanisms
        CKM_VENDOR_SM4_CBC, CKM_VENDOR_SM4_ECB};
      fullEncryptDecryptMechs = asSet(mechs);
    }

    return fullEncryptDecryptMechs.contains(mechCode);
  }

  /**
   * This method checks, if the mechanism with the given code is a
   * single-operation encrypt/decrypt mechanism; i.e. it does not support the
   * encryptUpdate() and decryptUpdate() functions.
   * If Returns true, the mechanism can be used with the encrypt
   * and decrypt functions excluding encryptUpdate and decryptUpdate.
   *
   * @param mechCode
   *          The code of the mechanism to check.
   * @return True, if the provided mechanism is a single-operation
   *         encrypt/decrypt mechanism. False, otherwise.
   */
  public static boolean isSingleOperationEncryptDecryptMechanism(
      long mechCode) {
    // build the hashtable on demand (=first use)
    if (sglOpEncryptDecryptMechs == null) {
      long[] mechs = new long[]{
        CKM_RSA_PKCS,
        CKM_RSA_PKCS_OAEP,
        CKM_RSA_X_509,
        CKM_RSA_PKCS_TPM_1_1,
        CKM_RSA_PKCS_OAEP_TPM_1_1};
      sglOpEncryptDecryptMechs = asSet(mechs);
    }

    return sglOpEncryptDecryptMechs.contains(mechCode);
  }

  /**
   * This method checks, if the mechanism with the given code is a full
   * sign/verify mechanism; i.e. it supports the signUpdate()
   * and verifyUpdate() functions.
   * If Returns true, the mechanism can be used with the sign and
   * verify functions including signUpdate and verifyUpdate.
   *
   * @param mechCode
   *          The code of the mechanism to check.
   * @return True, if the provided mechanism is a full sign/verify
   *         mechanism. False, otherwise.
   */
  public static boolean isFullSignVerifyMechanism(long mechCode) {
    // build the hashtable on demand (=first use)
    if (fullSignVerifyMechs == null) {
      long[] mechs = new long[]{
        CKM_SHA1_RSA_PKCS,
        CKM_SHA256_RSA_PKCS,
        CKM_SHA384_RSA_PKCS,
        CKM_SHA512_RSA_PKCS,
        CKM_SHA1_RSA_PKCS_PSS,
        CKM_SHA256_RSA_PKCS_PSS,
        CKM_SHA384_RSA_PKCS_PSS,
        CKM_SHA512_RSA_PKCS_PSS,
        CKM_SHA1_RSA_X9_31,
        CKM_DSA_SHA1,
        CKM_DSA_SHA224,
        CKM_DSA_SHA256,
        CKM_DSA_SHA384,
        CKM_DSA_SHA512,
        CKM_ECDSA_SHA1,
        CKM_AES_MAC_GENERAL,
        CKM_AES_MAC,
        CKM_AES_XCBC_MAC,
        CKM_AES_XCBC_MAC_96,
        CKM_AES_GMAC,
        CKM_AES_CMAC_GENERAL,
        CKM_AES_CMAC,
        CKM_DES3_MAC_GENERAL,
        CKM_DES3_MAC,
        CKM_DES3_CMAC_GENERAL,
        CKM_DES3_CMAC,
        CKM_SHA_1_HMAC_GENERAL,
        CKM_SHA_1_HMAC,
        CKM_SHA224_HMAC,
        CKM_SHA224_HMAC_GENERAL,
        CKM_SHA224_RSA_PKCS,
        CKM_SHA224_RSA_PKCS_PSS,
        CKM_SHA256_HMAC_GENERAL,
        CKM_SHA256_HMAC,
        CKM_SHA384_HMAC_GENERAL,
        CKM_SHA384_HMAC,
        CKM_SHA512_HMAC_GENERAL,
        CKM_SHA512_HMAC,
        CKM_SHA512_224_HMAC_GENERAL,
        CKM_SHA512_224_HMAC,
        CKM_SHA512_256_HMAC_GENERAL,
        CKM_SHA512_256_HMAC,
        CKM_SHA512_T_HMAC_GENERAL,
        CKM_SHA512_T_HMAC,
        CKM_SSL3_MD5_MAC,
        CKM_SSL3_SHA1_MAC,
        CKM_TLS10_MAC_SERVER,
        CKM_TLS10_MAC_CLIENT,
        CKM_TLS12_MAC,
        CKM_CMS_SIG,
        CKM_CAMELLIA_MAC_GENERAL,
        CKM_CAMELLIA_MAC,
        CKM_ARIA_MAC_GENERAL,
        CKM_ARIA_MAC,
        CKM_SECURID,
        CKM_HOTP,
        CKM_ACTI,
        CKM_KIP_MAC,
        CKM_GOST28147_MAC,
        CKM_GOSTR3411_HMAC,
        CKM_GOSTR3410_WITH_GOSTR3411,
        CKM_POLY1305,
        CKM_DSA_SHA3_224,
        CKM_DSA_SHA3_256,
        CKM_DSA_SHA3_384,
        CKM_DSA_SHA3_512,
        CKM_SHA3_224_RSA_PKCS,
        CKM_SHA3_256_RSA_PKCS,
        CKM_SHA3_384_RSA_PKCS,
        CKM_SHA3_512_RSA_PKCS,
        CKM_SHA3_224_RSA_PKCS_PSS,
        CKM_SHA3_256_RSA_PKCS_PSS,
        CKM_SHA3_384_RSA_PKCS_PSS,
        CKM_SHA3_512_RSA_PKCS_PSS,
        CKM_SHA3_224_HMAC,
        CKM_SHA3_224_HMAC_GENERAL,
        CKM_SHA3_256_HMAC,
        CKM_SHA3_256_HMAC_GENERAL,
        CKM_SHA3_384_HMAC,
        CKM_SHA3_384_HMAC_GENERAL,
        CKM_SHA3_512_HMAC,
        CKM_SHA3_512_HMAC_GENERAL,
        CKM_ECDSA_SHA3_224,
        CKM_ECDSA_SHA3_256,
        CKM_ECDSA_SHA3_384,
        CKM_ECDSA_SHA3_512,
        CKM_MD2_HMAC_GENERAL,
        CKM_MD2_HMAC,
        CKM_MD5_HMAC_GENERAL,
        CKM_MD5_HMAC,
        CKM_RIPEMD128_HMAC_GENERAL,
        CKM_RIPEMD128_HMAC,
        CKM_RIPEMD160_HMAC_GENERAL,
        CKM_RIPEMD160_HMAC,
        CKM_RIPEMD128_RSA_PKCS,
        CKM_RIPEMD160_RSA_PKCS,
        CKM_VENDOR_SM2,
        CKM_VENDOR_SM2_SM3,
        CKM_VENDOR_SM4_MAC_GENERAL,
        CKM_VENDOR_SM4_MAC,
        CKM_VENDOR_ISO2_SM4_MAC_GENERAL,
        CKM_VENDOR_ISO2_SM4_MAC,
        CKM_BLAKE2B_160_HMAC,
        CKM_BLAKE2B_160_HMAC_GENERAL,
        CKM_BLAKE2B_256_HMAC,
        CKM_BLAKE2B_256_HMAC_GENERAL,
        CKM_BLAKE2B_384_HMAC,
        CKM_BLAKE2B_384_HMAC_GENERAL,
        CKM_BLAKE2B_512_HMAC,
        CKM_BLAKE2B_512_HMAC_GENERAL,
        CKM_XEDDSA,
        CKM_EDDSA,
        // Vendor Mechanisms
        CKM_VENDOR_SM2, CKM_VENDOR_SM2_SM3, CKM_VENDOR_ISO2_SM4_MAC,
        CKM_VENDOR_SM4_MAC, CKM_VENDOR_SM4_MAC_GENERAL,
        CKM_VENDOR_ISO2_SM4_MAC, CKM_VENDOR_ISO2_SM4_MAC_GENERAL};
      fullSignVerifyMechs = asSet(mechs);
    }

    return fullSignVerifyMechs.contains(mechCode);
  }

  /**
   * This method checks, if the mechanism with the given code is a
   * single-operation sign/verify mechanism; i.e. it does not support the
   * signUpdate() and encryptUpdate() functions.
   * If Returns true, the mechanism can be used with the sign and
   * verify functions excluding signUpdate and encryptUpdate.
   *
   * @param mechCode
   *          The code of the mechanism to check.
   * @return True, if the provided mechanism is a single-operation
   *         sign/verify mechanism. False, otherwise.
   */
  public static boolean isSingleOperationSignVerifyMechanism(long mechCode) {
    // build the hashtable on demand (=first use)
    if (sglOpSignVerifyMechs == null) {
      long[] mechs = new long[]{
        CKM_RSA_PKCS,
        CKM_RSA_PKCS_PSS,
        CKM_RSA_9796,
        CKM_RSA_X_509,
        CKM_RSA_X9_31,
        CKM_DSA,
        CKM_ECDSA,
        CKM_GOSTR3410};
      sglOpSignVerifyMechs = asSet(mechs);
    }

    return sglOpSignVerifyMechs.contains(mechCode);
  }

  /**
   * This method checks, if the mechanism with the given code is a sign/verify
   * mechanism with message recovery.
   * If Returns true, the mechanism can be used with the
   * signRecover and verifyRecover functions.
   *
   * @param mechCode
   *          The code of the mechanism to check.
   * @return True, if the provided mechanism is a sign/verify mechanism with
   *         message recovery. False, otherwise.
   */
  public static boolean isSignVerifyRecoverMechanism(long mechCode) {
    // build the hashtable on demand (=first use)
    if (signVerifyRecoverMechs == null) {
      long[] mechs = new long[]{
        CKM_RSA_PKCS,
        CKM_RSA_9796,
        CKM_RSA_X_509,
        CKM_CMS_SIG,
        CKM_SEED_ECB,
        CKM_SEED_CBC,
        CKM_SEED_MAC_GENERAL};
      signVerifyRecoverMechs = asSet(mechs);
    }

    return signVerifyRecoverMechs.contains(mechCode);
  }

  /**
   * This method checks, if the mechanism with the given code is a digest
   * mechanism.
   * If Returns true, the mechanism can be used with the digest
   * functions.
   *
   * @param mechCode
   *          The code of the mechanism to check.
   * @return True, if the provided mechanism is a digest mechanism. False,
   *         otherwise.
   */
  public static boolean isDigestMechanism(long mechCode) {
    // build the hashtable on demand (=first use)
    if (digestMechs == null) {
      long[] mechs = new long[]{
        CKM_SHA_1,
        CKM_SHA224,
        CKM_SHA256,
        CKM_SHA384,
        CKM_SHA512,
        CKM_SHA512_224,
        CKM_SHA512_256,
        CKM_SHA512_T,
        CKM_SEED_MAC,
        CKM_GOSTR3411,
        CKM_SHA3_224,
        CKM_SHA3_256,
        CKM_SHA3_384,
        CKM_SHA3_512,
        CKM_MD2,
        CKM_MD5,
        CKM_RIPEMD128,
        CKM_RIPEMD160,
        CKM_VENDOR_SM3,
        CKM_BLAKE2B_160,
        CKM_BLAKE2B_256,
        CKM_BLAKE2B_384,
        CKM_BLAKE2B_512,
        // Vendor Mechanisms
        CKM_VENDOR_SM3};
      digestMechs = asSet(mechs);
    }

    return digestMechs.contains(mechCode);
  }

  /**
   * This method checks, if the mechanism with the given code is a key
   * generation mechanism for generating symmetric keys.
   * If Returns true, the mechanism can be used with the
   * generateKey function.
   *
   * @param mechCode
   *          The code of the mechanism to check.
   * @return True, if the provided mechanism is a key generation mechanism.
   *         False, otherwise.
   */
  public static boolean isKeyGenerationMechanism(long mechCode) {
    // build the hashtable on demand (=first use)
    if (keyGenMechs == null) {
      long[] mechs = new long[]{
        CKM_DSA_PARAMETER_GEN,
        CKM_DSA_PROBABLISTIC_PARAMETER_GEN,
        CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN,
        CKM_DH_PKCS_PARAMETER_GEN,
        CKM_GENERIC_SECRET_KEY_GEN,
        CKM_AES_KEY_GEN,
        CKM_AES_XTS_KEY_GEN,
        CKM_DES2_KEY_GEN,
        CKM_DES3_KEY_GEN,
        CKM_PBE_SHA1_DES3_EDE_CBC,
        CKM_PBE_SHA1_DES2_EDE_CBC,
        CKM_PBA_SHA1_WITH_SHA1_HMAC,
        CKM_PKCS5_PBKD2,
        CKM_SSL3_PRE_MASTER_KEY_GEN,
        CKM_WTLS_PRE_MASTER_KEY_GEN,
        CKM_CAMELLIA_KEY_GEN,
        CKM_ARIA_KEY_GEN,
        CKM_SEED_KEY_GEN,
        CKM_SECURID_KEY_GEN,
        CKM_HOTP_KEY_GEN,
        CKM_ACTI_KEY_GEN,
        CKM_GOST28147_KEY_GEN,
        CKM_CHACHA20_KEY_GEN,
        CKM_POLY1305_KEY_GEN,
        CKM_VENDOR_SM4_KEY_GEN,
        CKM_SHA_1_KEY_GEN,
        CKM_SHA224_KEY_GEN,
        CKM_SHA256_KEY_GEN,
        CKM_SHA384_KEY_GEN,
        CKM_SHA512_KEY_GEN,
        CKM_SHA512_224_KEY_GEN,
        CKM_SHA512_256_KEY_GEN,
        CKM_SHA512_T_KEY_GEN,
        CKM_BLAKE2B_160_KEY_GEN,
        CKM_BLAKE2B_256_KEY_GEN,
        CKM_BLAKE2B_384_KEY_GEN,
        CKM_BLAKE2B_512_KEY_GEN,
        CKM_HKDF_KEY_GEN,
        // Vendor Mechnisms
        CKM_VENDOR_SM4_KEY_GEN};
      keyGenMechs = asSet(mechs);
    }

    return keyGenMechs.contains(mechCode);
  }

  /**
   * This method checks, if the mechanism with the given code is a key-pair
   * generation mechanism for generating key-pairs.
   * If Returns true, the mechanism can be used with the
   * generateKeyPair function.
   *
   * @param mechCode
   *          The code of the mechanism to check.
   * @return True, if the provided mechanism is a key-pair generation
   *         mechanism. False, otherwise.
   */
  public static boolean isKeyPairGenerationMechanism(long mechCode) {
    // build the hashtable on demand (=first use)
    if (keyPairGenMechs == null) {
      long[] mechs = new long[]{
        CKM_RSA_PKCS_KEY_PAIR_GEN,
        CKM_RSA_X9_31_KEY_PAIR_GEN,
        CKM_DSA_KEY_PAIR_GEN,
        CKM_EC_KEY_PAIR_GEN,
        CKM_DH_PKCS_KEY_PAIR_GEN,
        CKM_X9_42_DH_KEY_PAIR_GEN,
        CKM_GOSTR3410_KEY_PAIR_GEN,
        CKM_VENDOR_SM2_KEY_PAIR_GEN,
        CKM_EC_EDWARDS_KEY_PAIR_GEN,
        CKM_EC_MONTGOMERY_KEY_PAIR_GEN,
        // Vendor Mechnisms
        CKM_VENDOR_SM2_KEY_PAIR_GEN};
      keyPairGenMechs = asSet(mechs);
    }

    return keyPairGenMechs.contains(mechCode);
  }

  /**
   * This method checks, if the mechanism with the given code is a
   * wrap/unwrap mechanism; i.e. it supports the wrapKey()
   * and unwrapKey() functions.
   * If Returns true, the mechanism can be used with the wrapKey
   * and unwrapKey functions.
   *
   * @param mechCode
   *          The code of the mechanism to check.
   * @return True, if the provided mechanism is a wrap/unwrap mechanism.
   *         False, otherwise.
   */
  public static boolean isWrapUnwrapMechanism(long mechCode) {
    // build the hashtable on demand (=first use)
    if (wrapUnwrapMechs == null) {
      long[] mechs = new long[] {
        CKM_RSA_PKCS,
        CKM_RSA_PKCS_OAEP,
        CKM_RSA_X_509,
        CKM_RSA_PKCS_TPM_1_1,
        CKM_RSA_PKCS_OAEP_TPM_1_1,
        CKM_ECDH_AES_KEY_WRAP,
        CKM_AES_ECB,
        CKM_AES_CBC,
        CKM_AES_CBC_PAD,
        CKM_AES_OFB,
        CKM_AES_CFB64,
        CKM_AES_CFB8,
        CKM_AES_CFB128,
        CKM_AES_CFB1,
        CKM_AES_XTS,
        CKM_AES_CTR,
        CKM_AES_CTS,
        CKM_AES_GCM,
        CKM_AES_CCM,
        CKM_AES_KEY_WRAP,
        CKM_AES_KEY_WRAP_PAD,
        CKM_AES_KEY_WRAP_KWP,
        CKM_DES3_ECB,
        CKM_DES3_CBC,
        CKM_DES3_CBC_PAD,
        CKM_BLOWFISH_CBC,
        CKM_BLOWFISH_CBC_PAD,
        CKM_CAMELLIA_ECB,
        CKM_CAMELLIA_CBC,
        CKM_CAMELLIA_CBC_PAD,
        CKM_ARIA_ECB,
        CKM_ARIA_CBC,
        CKM_ARIA_CBC_PAD,
        CKM_SEED_CBC_PAD,
        CKM_KIP_WRAP,
        CKM_GOST28147_ECB,
        CKM_GOST28147,
        CKM_GOST28147_KEY_WRAP,
        CKM_GOSTR3410_KEY_WRAP,
        CKM_CHACHA20,
        CKM_VENDOR_SM2_ENCRYPT,
        CKM_VENDOR_SM4_ECB,
        CKM_VENDOR_SM4_CBC,
        CKM_SALSA20,
        CKM_X2RATCHET_ENCRYPT,
        CKM_X2RATCHET_DECRYPT,
        // Vendor Mechanisms
        CKM_VENDOR_SM2_ENCRYPT, CKM_VENDOR_SM4_ECB};
      wrapUnwrapMechs = asSet(mechs);
    }

    return wrapUnwrapMechs.contains(mechCode);
  }

  /**
   * This method checks, if the mechanism with the given code is a key
   * derivation mechanism.
   * If Returns true, the mechanism can be used with the deriveKey
   * function.
   *
   * @param mechCode
   *          The code of the mechanism to check.
   * @return True, if the provided mechanism is a key derivation mechanism.
   *         False, otherwise.
   */
  public static boolean isKeyDerivationMechanism(long mechCode) {
    // build the hashtable on demand (=first use)
    if (keyDerivationMechs == null) {
      long[] mechs = new long[]{
        CKM_ECDH1_DERIVE,
        CKM_ECDH1_COFACTOR_DERIVE,
        CKM_ECMQV_DERIVE,
        CKM_DH_PKCS_DERIVE,
        CKM_X9_42_DH_DERIVE,
        CKM_X9_42_DH_HYBRID_DERIVE,
        CKM_X9_42_MQV_DERIVE,
        CKM_AES_GMAC,
        CKM_DES_ECB_ENCRYPT_DATA,
        CKM_DES_CBC_ENCRYPT_DATA,
        CKM_DES3_ECB_ENCRYPT_DATA,
        CKM_DES3_CBC_ENCRYPT_DATA,
        CKM_AES_ECB_ENCRYPT_DATA,
        CKM_AES_CBC_ENCRYPT_DATA,
        CKM_SHA1_KEY_DERIVATION,
        CKM_SHA224_KEY_DERIVATION,
        CKM_SHA256_KEY_DERIVATION,
        CKM_SHA384_KEY_DERIVATION,
        CKM_SHA512_KEY_DERIVATION,
        CKM_SHA512_224_KEY_DERIVATION,
        CKM_SHA512_256_KEY_DERIVATION,
        CKM_SHA512_T_KEY_DERIVATION,
        CKM_SSL3_MASTER_KEY_DERIVE,
        CKM_SSL3_MASTER_KEY_DERIVE_DH,
        CKM_SSL3_KEY_AND_MAC_DERIVE,
        CKM_TLS12_MASTER_KEY_DERIVE,
        CKM_TLS12_MASTER_KEY_DERIVE_DH,
        CKM_TLS12_KEY_AND_MAC_DERIVE,
        CKM_TLS12_KEY_SAFE_DERIVE,
        CKM_TLS_KDF,
        CKM_WTLS_MASTER_KEY_DERIVE,
        CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC,
        CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE,
        CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE,
        CKM_WTLS_PRF,
        CKM_CONCATENATE_BASE_AND_KEY,
        CKM_CONCATENATE_BASE_AND_DATA,
        CKM_CONCATENATE_DATA_AND_BASE,
        CKM_XOR_BASE_AND_DATA,
        CKM_EXTRACT_KEY_FROM_KEY,
        CKM_CAMELLIA_ECB_ENCRYPT_DATA,
        CKM_CAMELLIA_CBC_ENCRYPT_DATA,
        CKM_ARIA_ECB_ENCRYPT_DATA,
        CKM_ARIA_CBC_ENCRYPT_DATA,
        CKM_SEED_ECB_ENCRYPT_DATA,
        CKM_SEED_CBC_ENCRYPT_DATA,
        CKM_KIP_DERIVE,
        CKM_GOSTR3410_DERIVE,
        CKM_SHA3_224_KEY_DERIVE,
        CKM_SHA3_256_KEY_DERIVE,
        CKM_SHA3_384_KEY_DERIVE,
        CKM_SHA3_512_KEY_DERIVE,
        CKM_SHAKE_128_KEY_DERIVE,
        CKM_SHAKE_256_KEY_DERIVE,
        CKM_SHA256_KEY_DERIVATION,
        CKM_SHA256_KEY_DERIVATION,
        CKM_SHA256_KEY_DERIVATION,
        CKM_SHA256_KEY_DERIVATION,
        CKM_VENDOR_SM4_ECB_ENCRYPT_DATA,
        CKM_BLAKE2B_160_KEY_DERIVE,
        CKM_BLAKE2B_256_KEY_DERIVE,
        CKM_BLAKE2B_384_KEY_DERIVE,
        CKM_BLAKE2B_512_KEY_DERIVE,
        CKM_X3DH_INITIALIZE,
        CKM_X3DH_RESPOND,
        CKM_X2RATCHET_INITIALIZE,
        CKM_X2RATCHET_RESPOND,
        CKM_SP800_108_COUNTER_KDF,
        CKM_SP800_108_FEEDBACK_KDF,
        CKM_SP800_108_DOUBLE_PIPELINE_KDF,
        CKM_HKDF_DERIVE,
        CKM_HKDF_DATA,
        // Vendor Mechanisms
        CKM_VENDOR_SM4_ECB_ENCRYPT_DATA};
      keyDerivationMechs = asSet(mechs);
    }

    return keyDerivationMechs.contains(mechCode);
  }

  /**CKM_VENDOR_SM4_CBC
   * Converts a long value to a hexadecimal String of length 16. Includes
   * leading zeros if necessary.
   *
   * @param value
   *          The long value to be converted.
   * @return The hexadecimal string representation of the long value.
   */
  public static String toFullHex(long value) {
    long currentValue = value;
    StringBuilder stringBuffer = new StringBuilder(16);
    for (int j = 0; j < 16; j++) {
      int currentDigit = (int) currentValue & 0xf;
      stringBuffer.append(Hex.DIGITS[currentDigit]);
      currentValue >>>= 4;
    }

    return stringBuffer.reverse().toString();
  }

  /**
   * Converts a byte array to a hexadecimal String. Each byte is presented by
   * its two digit hex-code; 0x0A -> "0a", 0x00 -> "00". No leading "0x"
   * is included in the result.
   *
   * @param value
   *          the byte array to be converted
   * @return the hexadecimal string representation of the byte array
   */
  public static String toHexString(byte[] value) {
    return Hex.encode(value);
  }

  public static byte[] decodeHex(String encoded) {
    return Hex.decode(encoded);
  }

  public static String getHashAlgName(Mechanism hashMechanism) {
    return getHashAlgName(hashMechanism.getMechanismCode());
  }

  public static String getHashAlgName(long hashMechanism) {
    return hashMechCodeToHashNames.get(hashMechanism);
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy