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

org.xipki.security.pkcs11.P11Identity Maven / Gradle / Ivy

/*
 *
 * Copyright (c) 2013 - 2019 Lijun Liao
 *
 * 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 org.xipki.security.pkcs11;

import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;

import org.bouncycastle.jcajce.interfaces.EdDSAKey;
import org.bouncycastle.jcajce.interfaces.XDHKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xipki.security.EdECConstants;
import org.xipki.security.XiSecurityException;
import org.xipki.util.Args;
import org.xipki.util.CollectionUtil;

import iaik.pkcs.pkcs11.constants.Functions;
import iaik.pkcs.pkcs11.constants.PKCS11Constants;

/**
 * TODO.
 * @author Lijun Liao
 * @since 2.0.0
 */

public abstract class P11Identity implements Comparable {

  private static final Logger LOG = LoggerFactory.getLogger(P11Identity.class);

  protected final P11Slot slot;

  protected final P11IdentityId id;

  protected final PublicKey publicKey;

  private final int signatureKeyBitLength;

  protected X509Certificate[] certificateChain;

  protected P11Identity(P11Slot slot, P11IdentityId id, int signatureBitLen) {
    this.slot = Args.notNull(slot, "slot");
    this.id = Args.notNull(id, "id");
    this.publicKey = null;
    this.signatureKeyBitLength = signatureBitLen;
  } // constructor

  protected P11Identity(P11Slot slot, P11IdentityId id, PublicKey publicKey,
      X509Certificate[] certificateChain) {
    this.slot = Args.notNull(slot, "slot");
    this.id = Args.notNull(id, "id");

    if (certificateChain != null && certificateChain.length > 0 && certificateChain[0] != null) {
      this.publicKey = certificateChain[0].getPublicKey();
      this.certificateChain = certificateChain;
    } else if (publicKey != null) {
      this.publicKey = publicKey;
      this.certificateChain = null;
    } else {
      throw new IllegalArgumentException("neither certificate nor publicKey is non-null");
    }

    if (this.publicKey instanceof RSAPublicKey) {
      signatureKeyBitLength = ((RSAPublicKey) this.publicKey).getModulus().bitLength();
    } else if (this.publicKey instanceof ECPublicKey) {
      signatureKeyBitLength = ((ECPublicKey) this.publicKey).getParams().getOrder()
          .bitLength();
    } else if (this.publicKey instanceof DSAPublicKey) {
      signatureKeyBitLength = ((DSAPublicKey) this.publicKey).getParams().getQ().bitLength();
    } else if (this.publicKey instanceof EdDSAKey) {
      String algorithm = this.publicKey.getAlgorithm();
      if (EdECConstants.ALG_Ed25519.equalsIgnoreCase(algorithm)) {
        signatureKeyBitLength = 64;
      } else {
        throw new IllegalArgumentException("currently only " + EdECConstants.ALG_Ed25519
            + " curve is supported, but not " + algorithm);
      }
    } else if (this.publicKey instanceof XDHKey) {
      // no signature is supported
      signatureKeyBitLength = 0;
    } else {
      throw new IllegalArgumentException("currently only RSA, DSA, EC and Edwards public key are "
          + "supported, but not " + this.publicKey.getAlgorithm() + " (class: "
          + this.publicKey.getClass().getName() + ")");
    }
  } // constructor

  public byte[] sign(long mechanism, P11Params parameters, byte[] content)
      throws P11TokenException {
    if (publicKey instanceof XDHKey) {
      throw new P11TokenException("this identity is not suitable for sign");
    }

    Args.notNull(content, "content");
    slot.assertMechanismSupported(mechanism);
    if (!supportsMechanism(mechanism, parameters)) {
      throw new P11UnsupportedMechanismException(mechanism, id);
    }
    if (LOG.isDebugEnabled()) {
      LOG.debug("sign with mechanism {}", Functions.getMechanismDescription(mechanism));
    }
    return sign0(mechanism, parameters, content);
  }

  /**
   * Signs the content.
   *
   * @param mechanism
   *          mechanism to sign the content.
   * @param parameters
   *          Parameters. Could be {@code null}.
   * @param content
   *          Content to be signed. Must not be {@code null}.
   * @return signature.
   * @throws P11TokenException
   *         if PKCS#11 token error occurs.
   */
  protected abstract byte[] sign0(long mechanism, P11Params parameters, byte[] content)
      throws P11TokenException;

  public byte[] digestSecretKey(long mechanism) throws P11TokenException, XiSecurityException {
    slot.assertMechanismSupported(mechanism);
    if (LOG.isDebugEnabled()) {
      LOG.debug("digest secret with mechanism {}", Functions.getMechanismDescription(mechanism));
    }
    return digestSecretKey0(mechanism);
  }

  protected abstract byte[] digestSecretKey0(long mechanism) throws P11TokenException;

  public P11IdentityId getId() {
    return id;
  }

  public X509Certificate getCertificate() {
    return (certificateChain != null && certificateChain.length > 0) ? certificateChain[0] : null;
  }

  public X509Certificate[] certificateChain() {
    return (certificateChain == null) ? null
        : Arrays.copyOf(certificateChain, certificateChain.length);
  }

  public PublicKey getPublicKey() {
    return publicKey;
  }

  public void setCertificates(X509Certificate[] certificateChain) throws P11TokenException {
    if (CollectionUtil.isEmpty(certificateChain)) {
      this.certificateChain = null;
    } else {
      PublicKey pk = certificateChain[0].getPublicKey();
      if (!this.publicKey.equals(pk)) {
        throw new P11TokenException("certificateChain is not for the key");
      }
      this.certificateChain = certificateChain;
    }
  }

  public boolean match(P11IdentityId id) {
    return this.id.equals(id);
  }

  public boolean match(P11SlotIdentifier slotId, String keyLabel) {
    return id.match(slotId, keyLabel);
  }

  public int getSignatureKeyBitLength() {
    return signatureKeyBitLength;
  }

  @Override
  public int compareTo(P11Identity obj) {
    return id.compareTo(obj.id);
  }

  public boolean supportsMechanism(long mechanism, P11Params parameters) {
    if (publicKey == null) {
      if (PKCS11Constants.CKM_SHA_1_HMAC == mechanism
          || PKCS11Constants.CKM_SHA224_HMAC == mechanism
          || PKCS11Constants.CKM_SHA256_HMAC == mechanism
          || PKCS11Constants.CKM_SHA384_HMAC == mechanism
          || PKCS11Constants.CKM_SHA512_HMAC == mechanism
          || PKCS11Constants.CKM_SHA3_224_HMAC == mechanism
          || PKCS11Constants.CKM_SHA3_256_HMAC == mechanism
          || PKCS11Constants.CKM_SHA3_384_HMAC == mechanism
          || PKCS11Constants.CKM_SHA3_512_HMAC == mechanism) {
        return parameters == null;
      }
    }

    if (publicKey instanceof RSAPublicKey) {
      if (PKCS11Constants.CKM_RSA_9796 == mechanism
          || PKCS11Constants.CKM_RSA_PKCS == mechanism
          || PKCS11Constants.CKM_SHA1_RSA_PKCS == mechanism
          || PKCS11Constants.CKM_SHA224_RSA_PKCS == mechanism
          || PKCS11Constants.CKM_SHA256_RSA_PKCS == mechanism
          || PKCS11Constants.CKM_SHA384_RSA_PKCS == mechanism
          || PKCS11Constants.CKM_SHA512_RSA_PKCS == mechanism) {
        return parameters == null;
      } else if (PKCS11Constants.CKM_RSA_PKCS_PSS == mechanism
          || PKCS11Constants.CKM_SHA1_RSA_PKCS_PSS == mechanism
          || PKCS11Constants.CKM_SHA224_RSA_PKCS_PSS == mechanism
          || PKCS11Constants.CKM_SHA256_RSA_PKCS_PSS == mechanism
          || PKCS11Constants.CKM_SHA384_RSA_PKCS_PSS == mechanism
          || PKCS11Constants.CKM_SHA512_RSA_PKCS_PSS == mechanism) {
        return parameters instanceof P11Params.P11RSAPkcsPssParams;
      } else if (PKCS11Constants.CKM_RSA_X_509 == mechanism) {
        return parameters == null;
      }
    } else if (publicKey instanceof DSAPublicKey) {
      if (parameters != null) {
        return false;
      }
      if (PKCS11Constants.CKM_DSA == mechanism
          || PKCS11Constants.CKM_DSA_SHA1 == mechanism
          || PKCS11Constants.CKM_DSA_SHA224 == mechanism
          || PKCS11Constants.CKM_DSA_SHA256 == mechanism
          || PKCS11Constants.CKM_DSA_SHA384 == mechanism
          || PKCS11Constants.CKM_DSA_SHA512 == mechanism) {
        return true;
      }
    } else if (publicKey instanceof ECPublicKey) {
      if (PKCS11Constants.CKM_ECDSA == mechanism
          || PKCS11Constants.CKM_ECDSA_SHA1 == mechanism
          || PKCS11Constants.CKM_ECDSA_SHA224 == mechanism
          || PKCS11Constants.CKM_ECDSA_SHA256 == mechanism
          || PKCS11Constants.CKM_ECDSA_SHA384 == mechanism
          || PKCS11Constants.CKM_ECDSA_SHA512 == mechanism
          || PKCS11Constants.CKM_VENDOR_SM2 == mechanism) {
        return parameters == null;
      } else if (PKCS11Constants.CKM_VENDOR_SM2_SM3 == mechanism) {
        return parameters instanceof P11Params.P11ByteArrayParams;
      }
    } else if (publicKey instanceof EdDSAKey) {
      if (PKCS11Constants.CKM_EDDSA == mechanism) {
        return true;
      }
    }

    return false;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy