org.xipki.security.pkcs11.proxy.ProxyP11Slot Maven / Gradle / Ivy
The newest version!
/*
*
* Copyright (c) 2013 - 2017 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.proxy;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.List;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.xipki.common.util.StringUtil;
import org.xipki.security.X509Cert;
import org.xipki.security.exception.BadAsn1ObjectException;
import org.xipki.security.exception.P11TokenException;
import org.xipki.security.exception.P11UnknownEntityException;
import org.xipki.security.pkcs11.AbstractP11Slot;
import org.xipki.security.pkcs11.P11EntityIdentifier;
import org.xipki.security.pkcs11.P11Identity;
import org.xipki.security.pkcs11.P11MechanismFilter;
import org.xipki.security.pkcs11.P11NewKeyControl;
import org.xipki.security.pkcs11.P11ObjectIdentifier;
import org.xipki.security.pkcs11.P11SlotIdentifier;
import org.xipki.security.pkcs11.P11SlotRefreshResult;
import org.xipki.security.pkcs11.proxy.msg.Asn1CreateSecretKeyParams;
import org.xipki.security.pkcs11.proxy.msg.Asn1EntityIdAndCert;
import org.xipki.security.pkcs11.proxy.msg.Asn1GenDSAKeypairParams;
import org.xipki.security.pkcs11.proxy.msg.Asn1GenECKeypairParams;
import org.xipki.security.pkcs11.proxy.msg.Asn1GenRSAKeypairParams;
import org.xipki.security.pkcs11.proxy.msg.Asn1GenSecretKeyParams;
import org.xipki.security.pkcs11.proxy.msg.Asn1P11EntityIdentifier;
import org.xipki.security.pkcs11.proxy.msg.Asn1P11ObjectIdentifier;
import org.xipki.security.pkcs11.proxy.msg.Asn1P11ObjectIdentifiers;
import org.xipki.security.pkcs11.proxy.msg.Asn1P11SlotIdentifier;
import org.xipki.security.pkcs11.proxy.msg.Asn1RemoveObjectsParams;
import org.xipki.security.util.KeyUtil;
import org.xipki.security.util.X509Util;
/**
* @author Lijun Liao
* @since 2.0.0
*/
public class ProxyP11Slot extends AbstractP11Slot {
private final ProxyP11Module module;
private final P11SlotIdentifier slotId;
ProxyP11Slot(final ProxyP11Module module, final P11SlotIdentifier slotId,
final boolean readOnly, final P11MechanismFilter mechanismFilter)
throws P11TokenException {
super(module.getName(), slotId, readOnly, mechanismFilter);
this.module = module;
this.slotId = slotId;
refresh();
}
@Override
protected P11SlotRefreshResult refresh0()
throws P11TokenException {
P11SlotRefreshResult refreshResult = new P11SlotRefreshResult();
// mechanisms
List mechs = getMechanismsFromServer();
for (Long mech : mechs) {
refreshResult.addMechanism(mech);
}
// certificates
List certIds =
getObjectIdsFromServer(P11ProxyConstants.ACTION_GET_CERT_IDS);
for (P11ObjectIdentifier certId : certIds) {
X509Cert cert = getCertificate(certId);
if (cert != null) {
refreshResult.addCertificate(certId, cert);
}
}
List keyIds =
getObjectIdsFromServer(P11ProxyConstants.ACTION_GET_IDENTITY_IDS);
for (P11ObjectIdentifier keyId : keyIds) {
byte[] id = keyId.id();
java.security.PublicKey pubKey = null;
X509Cert cert = refreshResult.getCertForId(id);
if (cert != null) {
pubKey = cert.cert().getPublicKey();
} else {
pubKey = getPublicKey(keyId);
}
P11EntityIdentifier entityId = new P11EntityIdentifier(slotId, keyId);
ProxyP11Identity identity;
if (pubKey == null) {
identity = new ProxyP11Identity(this, entityId);
} else {
X509Certificate[] certs = (cert == null)
? null : new X509Certificate[]{cert.cert()};
identity = new ProxyP11Identity(this, entityId, pubKey, certs);
}
refreshResult.addIdentity(identity);
}
return refreshResult;
}
@Override
public void close() {
}
private PublicKey getPublicKey(final P11ObjectIdentifier objectId)
throws P11UnknownEntityException, P11TokenException {
P11EntityIdentifier entityId = new P11EntityIdentifier(slotId, objectId);
byte[] resp = module.send(P11ProxyConstants.ACTION_GET_PUBLICKEY,
new Asn1P11EntityIdentifier(entityId));
if (resp == null) {
return null;
}
SubjectPublicKeyInfo pkInfo = SubjectPublicKeyInfo.getInstance(resp);
try {
return KeyUtil.generatePublicKey(pkInfo);
} catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
throw new P11TokenException("could not generate Public Key from SubjectPublicKeyInfo:"
+ ex.getMessage(), ex);
}
}
private X509Cert getCertificate(final P11ObjectIdentifier certId) throws P11TokenException {
P11EntityIdentifier entityId = new P11EntityIdentifier(slotId, certId);
byte[] resp = module.send(P11ProxyConstants.ACTION_GET_CERT,
new Asn1P11EntityIdentifier(entityId));
if (resp == null) {
return null;
}
try {
return new X509Cert(X509Util.parseCert(resp), resp);
} catch (CertificateException ex) {
throw new P11TokenException("could not parse certificate:" + ex.getMessage(), ex);
}
}
@Override
public int removeObjects(final byte[] id, final String label) throws P11TokenException {
if ((id == null || id.length == 0) && StringUtil.isBlank(label)) {
throw new IllegalArgumentException("at least one of id and label must not be null");
}
Asn1RemoveObjectsParams params = new Asn1RemoveObjectsParams(slotId, id, label);
byte[] resp = module.send(P11ProxyConstants.ACTION_REMOVE_OBJECTS, params);
try {
return ASN1Integer.getInstance(resp).getValue().intValue();
} catch (IllegalArgumentException ex) {
throw new P11TokenException(ex.getMessage(), ex);
}
}
@Override
protected void removeIdentity0(final P11ObjectIdentifier objectId) throws P11TokenException {
Asn1P11EntityIdentifier asn1EntityId = new Asn1P11EntityIdentifier(slotId, objectId);
module.send(P11ProxyConstants.ACTION_REMOVE_IDENTITY, asn1EntityId);
}
@Override
protected void addCert0(final P11ObjectIdentifier objectId, final X509Certificate cert)
throws P11TokenException, CertificateException {
Asn1EntityIdAndCert asn1 = new Asn1EntityIdAndCert(
new P11EntityIdentifier(slotId, objectId), cert);
module.send(P11ProxyConstants.ACTION_ADD_CERT, asn1);
}
@Override
protected void removeCerts0(final P11ObjectIdentifier objectId) throws P11TokenException {
Asn1P11EntityIdentifier asn1EntityId = new Asn1P11EntityIdentifier(slotId, objectId);
module.send(P11ProxyConstants.ACTION_REMOVE_CERTS, asn1EntityId);
}
@Override
protected P11Identity generateSecretKey0(long keyType, int keysize, String label,
final P11NewKeyControl control)
throws P11TokenException {
Asn1GenSecretKeyParams asn1 = new Asn1GenSecretKeyParams(
slotId, label, control, keyType, keysize);
byte[] resp = module.send(P11ProxyConstants.ACTION_GEN_SECRET_KEY, asn1);
return parseGenerateSecretKeyResult(resp);
}
@Override
protected P11Identity createSecretKey0(long keyType, byte[] keyValue, String label,
final P11NewKeyControl control)
throws P11TokenException {
Asn1CreateSecretKeyParams asn1 = new Asn1CreateSecretKeyParams(
slotId, label, control, keyType, keyValue);
byte[] resp = module.send(P11ProxyConstants.ACTION_CREATE_SECRET_KEY, asn1);
return parseGenerateSecretKeyResult(resp);
}
@Override
protected P11Identity generateRSAKeypair0(final int keysize, final BigInteger publicExponent,
final String label, final P11NewKeyControl control) throws P11TokenException {
Asn1GenRSAKeypairParams asn1 = new Asn1GenRSAKeypairParams(slotId, label, control,
keysize, publicExponent);
byte[] resp = module.send(P11ProxyConstants.ACTION_GEN_KEYPAIR_RSA, asn1);
return parseGenerateKeypairResult(resp);
}
@Override
// CHECKSTYLE:OFF
protected P11Identity generateDSAKeypair0(final BigInteger p, final BigInteger q,
final BigInteger g, final String label, final P11NewKeyControl control)
throws P11TokenException {
// CHECKSTYLE:ON
Asn1GenDSAKeypairParams asn1 = new Asn1GenDSAKeypairParams(slotId, label,
control, p, q, g);
byte[] resp = module.send(P11ProxyConstants.ACTION_GEN_KEYPAIR_DSA, asn1);
return parseGenerateKeypairResult(resp);
}
@Override
protected P11Identity generateECKeypair0(final ASN1ObjectIdentifier curveId,
final String label, final P11NewKeyControl control) throws P11TokenException {
Asn1GenECKeypairParams asn1 = new Asn1GenECKeypairParams(slotId, label, control,
curveId);
byte[] resp = module.send(P11ProxyConstants.ACTION_GEN_KEYPAIR_EC, asn1);
return parseGenerateKeypairResult(resp);
}
private P11Identity parseGenerateKeypairResult(final byte[] resp)
throws P11TokenException {
if (resp == null) {
throw new P11TokenException("server returned no result");
}
Asn1P11EntityIdentifier ei;
try {
ei = Asn1P11EntityIdentifier.getInstance(resp);
} catch (BadAsn1ObjectException ex) {
throw new P11TokenException(
"invalid ASN1 object Asn1P11EntityIdentifier: " + ex.getMessage(), ex);
}
if (!slotId.equals(ei.slotId().slotId())) {
throw new P11TokenException("");
}
P11EntityIdentifier entityId = ei.entityId();
PublicKey publicKey = getPublicKey(entityId.objectId());
return new ProxyP11Identity(this, entityId, publicKey, null);
}
private P11Identity parseGenerateSecretKeyResult(final byte[] resp)
throws P11TokenException {
if (resp == null) {
throw new P11TokenException("server returned no result");
}
Asn1P11EntityIdentifier ei;
try {
ei = Asn1P11EntityIdentifier.getInstance(resp);
} catch (BadAsn1ObjectException ex) {
throw new P11TokenException(
"invalid ASN1 object Asn1P11EntityIdentifier: " + ex.getMessage(), ex);
}
if (!slotId.equals(ei.slotId().slotId())) {
throw new P11TokenException("");
}
P11EntityIdentifier entityId = ei.entityId();
return new ProxyP11Identity(this, entityId);
}
@Override
protected void updateCertificate0(final P11ObjectIdentifier objectId,
final X509Certificate newCert)
throws P11TokenException, CertificateException {
Asn1EntityIdAndCert asn1 = new Asn1EntityIdAndCert(
new P11EntityIdentifier(slotId, objectId), newCert);
module.send(P11ProxyConstants.ACTION_UPDATE_CERT, asn1);
}
private List getMechanismsFromServer() throws P11TokenException {
Asn1P11SlotIdentifier asn1SlotId = new Asn1P11SlotIdentifier(slotId);
byte[] resp = module.send(P11ProxyConstants.ACTION_GET_MECHANISMS, asn1SlotId);
ASN1Sequence seq = requireSequence(resp);
final int n = seq.size();
List mechs = new ArrayList<>(n);
for ( int i = 0; i < n; i++) {
long mech = ASN1Integer.getInstance(seq.getObjectAt(i)).getValue().longValue();
mechs.add(mech);
}
return mechs;
}
private List getObjectIdsFromServer(final short action)
throws P11TokenException {
Asn1P11SlotIdentifier asn1SlotId = new Asn1P11SlotIdentifier(slotId);
byte[] resp = module.send(action, asn1SlotId);
List asn1ObjectIds;
try {
asn1ObjectIds = Asn1P11ObjectIdentifiers.getInstance(resp).objectIds();
} catch (BadAsn1ObjectException ex) {
throw new P11TokenException("bad ASN1 object: " + ex.getMessage(), ex);
}
List objectIds = new ArrayList<>(asn1ObjectIds.size());
for (Asn1P11ObjectIdentifier asn1Id : asn1ObjectIds) {
objectIds.add(asn1Id.objectId());
}
return objectIds;
}
private ASN1Sequence requireSequence(final byte[] response) throws P11TokenException {
try {
return ASN1Sequence.getInstance(response);
} catch (IllegalArgumentException ex) {
throw new P11TokenException("response is not ASN1Sequence", ex);
}
}
ProxyP11Module module() {
return module;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy