org.xipki.security.pkcs11.proxy.ProxyP11Slot 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.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.ASN1Object;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.xipki.security.BadAsn1ObjectException;
import org.xipki.security.X509Cert;
import org.xipki.security.pkcs11.P11Identity;
import org.xipki.security.pkcs11.P11IdentityId;
import org.xipki.security.pkcs11.P11ModuleConf.P11MechanismFilter;
import org.xipki.security.pkcs11.P11ObjectIdentifier;
import org.xipki.security.pkcs11.P11Slot;
import org.xipki.security.pkcs11.P11SlotIdentifier;
import org.xipki.security.pkcs11.P11TokenException;
import org.xipki.security.pkcs11.P11UnknownEntityException;
import org.xipki.security.util.KeyUtil;
import org.xipki.security.util.X509Util;
import org.xipki.util.StringUtil;
/**
* TODO.
* @author Lijun Liao
* @since 2.0.0
*/
public class ProxyP11Slot extends P11Slot {
private final ProxyP11Module module;
private final P11SlotIdentifier slotId;
private final ProxyMessage.SlotIdentifier asn1SlotId;
ProxyP11Slot(ProxyP11Module module, P11SlotIdentifier slotId, boolean readOnly,
P11MechanismFilter mechanismFilter) throws P11TokenException {
super(module.getName(), slotId, readOnly, mechanismFilter);
this.module = module;
this.slotId = slotId;
this.asn1SlotId = new ProxyMessage.SlotIdentifier(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);
}
}
// public keys
List pubkeyIds =
getObjectIdsFromServer(P11ProxyConstants.ACTION_GET_PUBLICKEY_IDS);
List keyIds =
getObjectIdsFromServer(P11ProxyConstants.ACTION_GET_IDENTITY_IDS);
for (P11ObjectIdentifier keyId : keyIds) {
byte[] id = keyId.getId();
// find the label of public key
P11ObjectIdentifier pubkeyid = null;
for (P11ObjectIdentifier m : pubkeyIds) {
if (m.matchesId(id)) {
pubkeyid = m;
break;
}
}
java.security.PublicKey pubKey = null;
X509Cert cert = refreshResult.getCertForId(id);
if (cert != null) {
pubKey = cert.getCert().getPublicKey();
} else {
pubKey = getPublicKey(keyId);
}
P11IdentityId entityId = new P11IdentityId(slotId, keyId,
(pubkeyid == null ? null : pubkeyid.getLabel()),
refreshResult.getCertLabelForId(id));
ProxyP11Identity identity;
if (pubKey == null) {
identity = new ProxyP11Identity(this, entityId);
} else {
X509Certificate[] certs = (cert == null) ? null : new X509Certificate[]{cert.getCert()};
identity = new ProxyP11Identity(this, entityId, pubKey, certs);
}
refreshResult.addIdentity(identity);
}
return refreshResult;
}
@Override
public void close() {
}
private PublicKey getPublicKey(P11ObjectIdentifier objectId)
throws P11UnknownEntityException, P11TokenException {
ASN1Object req =
new ProxyMessage.SlotIdAndObjectId(asn1SlotId, new ProxyMessage.ObjectIdentifier(objectId));
byte[] resp = module.send(P11ProxyConstants.ACTION_GET_PUBLICKEY, req);
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(P11ObjectIdentifier objectId) throws P11TokenException {
ASN1Object req =
new ProxyMessage.SlotIdAndObjectId(asn1SlotId, new ProxyMessage.ObjectIdentifier(objectId));
byte[] resp = module.send(P11ProxyConstants.ACTION_GET_CERT, req);
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(byte[] id, 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");
}
ProxyMessage.RemoveObjectsParams params =
new ProxyMessage.RemoveObjectsParams(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(P11IdentityId identityId) throws P11TokenException {
ASN1Object req = new ProxyMessage.SlotIdAndObjectId(asn1SlotId,
new ProxyMessage.ObjectIdentifier(identityId.getKeyId()));
module.send(P11ProxyConstants.ACTION_REMOVE_IDENTITY, req);
}
@Override
protected P11ObjectIdentifier addCert0(X509Certificate cert, P11NewObjectControl control)
throws P11TokenException, CertificateException {
ProxyMessage.AddCertParams asn1 = new ProxyMessage.AddCertParams(slotId, control, cert);
byte[] resp = module.send(P11ProxyConstants.ACTION_ADD_CERT, asn1);
if (resp == null) {
return null;
}
ProxyMessage.ObjectIdentifier objId;
try {
objId = ProxyMessage.ObjectIdentifier.getInstance(resp);
} catch (BadAsn1ObjectException ex) {
throw new P11TokenException(
"invalid ASN1 object Asn1P11ObjectIdentifier: " + ex.getMessage(), ex);
}
return objId.getValue();
}
@Override
protected void removeCerts0(P11ObjectIdentifier objectId) throws P11TokenException {
ASN1Object req =
new ProxyMessage.SlotIdAndObjectId(asn1SlotId, new ProxyMessage.ObjectIdentifier(objectId));
module.send(P11ProxyConstants.ACTION_REMOVE_CERTS, req);
}
@Override
protected P11Identity generateSecretKey0(long keyType, int keysize, P11NewKeyControl control)
throws P11TokenException {
ProxyMessage.GenSecretKeyParams asn1 = new ProxyMessage.GenSecretKeyParams(
slotId, control, keyType, keysize);
byte[] resp = module.send(P11ProxyConstants.ACTION_GEN_SECRET_KEY, asn1);
return parseGenerateSecretKeyResult(resp);
}
@Override
protected P11Identity importSecretKey0(long keyType, byte[] keyValue, P11NewKeyControl control)
throws P11TokenException {
ProxyMessage.ImportSecretKeyParams asn1 = new ProxyMessage.ImportSecretKeyParams(
slotId, control, keyType, keyValue);
byte[] resp = module.send(P11ProxyConstants.ACTION_IMPORT_SECRET_KEY, asn1);
return parseGenerateSecretKeyResult(resp);
}
@Override
protected P11Identity generateRSAKeypair0(int keysize, BigInteger publicExponent,
P11NewKeyControl control) throws P11TokenException {
ProxyMessage.GenRSAKeypairParams asn1 = new ProxyMessage.GenRSAKeypairParams(
slotId, control, keysize, publicExponent);
byte[] resp = module.send(P11ProxyConstants.ACTION_GEN_KEYPAIR_RSA, asn1);
return parseGenerateKeypairResult(resp);
}
@Override
protected P11Identity generateDSAKeypair0(BigInteger p, BigInteger q, BigInteger g,
P11NewKeyControl control) throws P11TokenException {
ProxyMessage.GenDSAKeypairParams asn1 =
new ProxyMessage.GenDSAKeypairParams(slotId, control, p, q, g);
byte[] resp = module.send(P11ProxyConstants.ACTION_GEN_KEYPAIR_DSA, asn1);
return parseGenerateKeypairResult(resp);
}
@Override
protected P11Identity generateECKeypair0(ASN1ObjectIdentifier curveId, P11NewKeyControl control)
throws P11TokenException {
ProxyMessage.GenECKeypairParams asn1 =
new ProxyMessage.GenECKeypairParams(slotId, control, curveId);
byte[] resp = module.send(P11ProxyConstants.ACTION_GEN_KEYPAIR_EC, asn1);
return parseGenerateKeypairResult(resp);
}
@Override
protected P11Identity generateSM2Keypair0(P11NewKeyControl control) throws P11TokenException {
ProxyMessage.GenSM2KeypairParams asn1 =
new ProxyMessage.GenSM2KeypairParams(slotId, control);
byte[] resp = module.send(P11ProxyConstants.ACTION_GEN_KEYPAIR_SM2, asn1);
return parseGenerateKeypairResult(resp);
}
private P11Identity parseGenerateKeypairResult(byte[] resp) throws P11TokenException {
return parseGenerateKeyResult(resp, true);
}
private P11Identity parseGenerateSecretKeyResult(byte[] resp) throws P11TokenException {
return parseGenerateKeyResult(resp, false);
}
private P11Identity parseGenerateKeyResult(byte[] resp, boolean needsPublicKey)
throws P11TokenException {
if (resp == null) {
throw new P11TokenException("server returned no result");
}
ProxyMessage.IdentityId ei;
try {
ei = ProxyMessage.IdentityId.getInstance(resp);
} catch (BadAsn1ObjectException ex) {
throw new P11TokenException(
"invalid ASN1 object Asn1P11EntityIdentifier: " + ex.getMessage(), ex);
}
if (!slotId.equals(ei.getValue().getSlotId())) {
throw new P11TokenException("returned identity has different slodId");
}
P11IdentityId identityId = ei.getValue();
if (needsPublicKey) {
PublicKey publicKey = getPublicKey(identityId.getPublicKeyId());
return new ProxyP11Identity(this, identityId, publicKey, null);
} else {
return new ProxyP11Identity(this, identityId);
}
}
@Override
protected void updateCertificate0(P11ObjectIdentifier objectId, X509Certificate newCert)
throws P11TokenException, CertificateException {
ProxyMessage.ObjectIdAndCert asn1 = new ProxyMessage.ObjectIdAndCert(asn1SlotId,
new ProxyMessage.ObjectIdentifier(objectId), newCert);
module.send(P11ProxyConstants.ACTION_UPDATE_CERT, asn1);
}
private List getMechanismsFromServer() throws P11TokenException {
ProxyMessage.SlotIdentifier asn1SlotId = new ProxyMessage.SlotIdentifier(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(short action)
throws P11TokenException {
ProxyMessage.SlotIdentifier asn1SlotId = new ProxyMessage.SlotIdentifier(slotId);
byte[] resp = module.send(action, asn1SlotId);
List asn1ObjectIds;
try {
asn1ObjectIds = ProxyMessage.ObjectIdentifiers.getInstance(resp).getObjectIds();
} catch (BadAsn1ObjectException ex) {
throw new P11TokenException("bad ASN1 object: " + ex.getMessage(), ex);
}
List objectIds = new ArrayList<>(asn1ObjectIds.size());
for (ProxyMessage.ObjectIdentifier asn1Id : asn1ObjectIds) {
objectIds.add(asn1Id.getValue());
}
return objectIds;
}
private ASN1Sequence requireSequence(byte[] response) throws P11TokenException {
try {
return ASN1Sequence.getInstance(response);
} catch (IllegalArgumentException ex) {
throw new P11TokenException("response is not ASN1Sequence", ex);
}
}
ProxyP11Module getModule() {
return module;
}
ProxyMessage.SlotIdentifier getAsn1SlotId() {
return asn1SlotId;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy