0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: /**
0019: * @author Alexander Y. Kleymenov
0020: * @version $Revision$
0021: */package java.security.cert;
0022:
0023: import java.io.IOException;
0024: import java.math.BigInteger;
0025: import java.security.PublicKey;
0026: import java.security.cert.CertSelector;
0027: import java.security.cert.X509Certificate;
0028: import java.util.ArrayList;
0029: import java.util.Arrays;
0030: import java.util.Collection;
0031: import java.util.Collections;
0032: import java.util.Date;
0033: import java.util.HashSet;
0034: import java.util.Iterator;
0035: import java.util.List;
0036: import java.util.Set;
0037: import javax.security.auth.x500.X500Principal;
0038:
0039: import org.apache.harmony.security.asn1.ASN1OctetString;
0040: import org.apache.harmony.security.internal.nls.Messages;
0041: import org.apache.harmony.security.x509.AlgorithmIdentifier;
0042: import org.apache.harmony.security.x509.CertificatePolicies;
0043: import org.apache.harmony.security.x509.GeneralName;
0044: import org.apache.harmony.security.x509.GeneralNames;
0045: import org.apache.harmony.security.x509.NameConstraints;
0046: import org.apache.harmony.security.x509.PolicyInformation;
0047: import org.apache.harmony.security.x509.PrivateKeyUsagePeriod;
0048: import org.apache.harmony.security.x509.SubjectPublicKeyInfo;
0049:
0050: /**
0051: * @com.intel.drl.spec_ref
0052: */
0053: public class X509CertSelector implements CertSelector {
0054:
0055: // match criteria
0056: private X509Certificate certificateEquals;
0057: private BigInteger serialNumber;
0058: private X500Principal issuer;
0059: private X500Principal subject;
0060: private byte[] subjectKeyIdentifier;
0061: private byte[] authorityKeyIdentifier;
0062: private Date certificateValid;
0063: private String subjectPublicKeyAlgID;
0064: private Date privateKeyValid;
0065: private byte[] subjectPublicKey;
0066: private boolean[] keyUsage;
0067: private Set extendedKeyUsage;
0068: private boolean matchAllNames = true;
0069: private int pathLen = -1;
0070: private List[] subjectAltNames;
0071: private NameConstraints nameConstraints;
0072: private Set policies;
0073: private ArrayList pathToNames;
0074:
0075: // needed to avoid needless encoding/decoding work
0076: private PublicKey subjectPublicKeyImpl;
0077: private String issuerName;
0078: private byte[] issuerBytes;
0079:
0080: /**
0081: * @com.intel.drl.spec_ref
0082: */
0083: public X509CertSelector() {
0084: }
0085:
0086: /**
0087: * @com.intel.drl.spec_ref
0088: */
0089: public void setCertificate(X509Certificate certificate) {
0090: certificateEquals = certificate;
0091: }
0092:
0093: /**
0094: * @com.intel.drl.spec_ref
0095: */
0096: public X509Certificate getCertificate() {
0097: return certificateEquals;
0098: }
0099:
0100: /**
0101: * @com.intel.drl.spec_ref
0102: */
0103: public void setSerialNumber(BigInteger serialNumber) {
0104: this .serialNumber = serialNumber;
0105: }
0106:
0107: /**
0108: * @com.intel.drl.spec_ref
0109: */
0110: public BigInteger getSerialNumber() {
0111: return serialNumber;
0112: }
0113:
0114: /**
0115: * @com.intel.drl.spec_ref
0116: */
0117: public void setIssuer(X500Principal issuer) {
0118: this .issuer = issuer;
0119: this .issuerName = null;
0120: this .issuerBytes = null;
0121: }
0122:
0123: /**
0124: * @com.intel.drl.spec_ref
0125: */
0126: public X500Principal getIssuer() {
0127: return issuer;
0128: }
0129:
0130: /**
0131: * @com.intel.drl.spec_ref
0132: */
0133: public void setIssuer(String issuerName) throws IOException {
0134: if (issuerName == null) {
0135: this .issuer = null;
0136: this .issuerName = null;
0137: this .issuerBytes = null;
0138: return;
0139: }
0140: try {
0141: this .issuer = new X500Principal(issuerName);
0142: this .issuerName = issuerName;
0143: this .issuerBytes = null;
0144: } catch (IllegalArgumentException e) {
0145: throw new IOException(e.getMessage());
0146: }
0147: }
0148:
0149: /**
0150: * @com.intel.drl.spec_ref
0151: */
0152: public String getIssuerAsString() {
0153: if (issuer == null) {
0154: return null;
0155: }
0156: if (issuerName == null) {
0157: issuerName = issuer.getName();
0158: }
0159: return issuerName;
0160: }
0161:
0162: /**
0163: * @com.intel.drl.spec_ref
0164: */
0165: public void setIssuer(byte[] issuerDN) throws IOException {
0166: if (issuerDN == null) {
0167: issuer = null;
0168: return;
0169: }
0170: try {
0171: issuer = new X500Principal(issuerDN);
0172: this .issuerName = null;
0173: this .issuerBytes = new byte[issuerDN.length];
0174: System.arraycopy(issuerDN, 0, this .issuerBytes, 0,
0175: issuerDN.length);
0176: } catch (IllegalArgumentException e) {
0177: throw new IOException(e.getMessage());
0178: }
0179: }
0180:
0181: /**
0182: * @com.intel.drl.spec_ref
0183: */
0184: public byte[] getIssuerAsBytes() throws IOException {
0185: if (issuer == null) {
0186: return null;
0187: }
0188: if (issuerBytes == null) {
0189: issuerBytes = issuer.getEncoded();
0190: }
0191: byte[] result = new byte[issuerBytes.length];
0192: System.arraycopy(issuerBytes, 0, result, 0, issuerBytes.length);
0193: return result;
0194: }
0195:
0196: /**
0197: * @com.intel.drl.spec_ref
0198: */
0199: public void setSubject(X500Principal subject) {
0200: this .subject = subject;
0201: }
0202:
0203: /**
0204: * @com.intel.drl.spec_ref
0205: */
0206: public X500Principal getSubject() {
0207: return subject;
0208: }
0209:
0210: /**
0211: * @com.intel.drl.spec_ref
0212: */
0213: public void setSubject(String subjectDN) throws IOException {
0214: if (subjectDN == null) {
0215: subject = null;
0216: return;
0217: }
0218: try {
0219: subject = new X500Principal(subjectDN);
0220: } catch (IllegalArgumentException e) {
0221: throw new IOException(e.getMessage());
0222: }
0223: }
0224:
0225: /**
0226: * @com.intel.drl.spec_ref
0227: */
0228: public String getSubjectAsString() {
0229: if (subject == null) {
0230: return null;
0231: }
0232: return subject.getName();
0233: }
0234:
0235: /**
0236: * @com.intel.drl.spec_ref
0237: */
0238: public void setSubject(byte[] subjectDN) throws IOException {
0239: if (subjectDN == null) {
0240: subject = null;
0241: return;
0242: }
0243: try {
0244: subject = new X500Principal(subjectDN);
0245: } catch (IllegalArgumentException e) {
0246: throw new IOException(e.getMessage());
0247: }
0248: }
0249:
0250: /**
0251: * @com.intel.drl.spec_ref
0252: */
0253: public byte[] getSubjectAsBytes() throws IOException {
0254: if (subject == null) {
0255: return null;
0256: }
0257: return subject.getEncoded();
0258: }
0259:
0260: /**
0261: * @com.intel.drl.spec_ref
0262: */
0263: public void setSubjectKeyIdentifier(byte[] subjectKeyIdentifier) {
0264: if (subjectKeyIdentifier == null) {
0265: this .subjectKeyIdentifier = null;
0266: return;
0267: }
0268: this .subjectKeyIdentifier = new byte[subjectKeyIdentifier.length];
0269: System.arraycopy(subjectKeyIdentifier, 0,
0270: this .subjectKeyIdentifier, 0,
0271: subjectKeyIdentifier.length);
0272: }
0273:
0274: /**
0275: * @com.intel.drl.spec_ref
0276: */
0277: public byte[] getSubjectKeyIdentifier() {
0278: if (subjectKeyIdentifier == null) {
0279: return null;
0280: }
0281: byte[] res = new byte[subjectKeyIdentifier.length];
0282: System.arraycopy(subjectKeyIdentifier, 0, res, 0, res.length);
0283: return res;
0284: }
0285:
0286: /**
0287: * @com.intel.drl.spec_ref
0288: */
0289: public void setAuthorityKeyIdentifier(byte[] authorityKeyIdentifier) {
0290: if (authorityKeyIdentifier == null) {
0291: this .authorityKeyIdentifier = null;
0292: return;
0293: }
0294: this .authorityKeyIdentifier = new byte[authorityKeyIdentifier.length];
0295: System.arraycopy(authorityKeyIdentifier, 0,
0296: this .authorityKeyIdentifier, 0,
0297: authorityKeyIdentifier.length);
0298: }
0299:
0300: /**
0301: * @com.intel.drl.spec_ref
0302: */
0303: public byte[] getAuthorityKeyIdentifier() {
0304: if (authorityKeyIdentifier == null) {
0305: return null;
0306: }
0307: byte[] res = new byte[authorityKeyIdentifier.length];
0308: System.arraycopy(authorityKeyIdentifier, 0, res, 0, res.length);
0309: return res;
0310: }
0311:
0312: /**
0313: * @com.intel.drl.spec_ref
0314: */
0315: public void setCertificateValid(Date certificateValid) {
0316: this .certificateValid = (certificateValid == null) ? null
0317: : (Date) certificateValid.clone();
0318: }
0319:
0320: /**
0321: * @com.intel.drl.spec_ref
0322: */
0323: public Date getCertificateValid() {
0324: return (certificateValid == null) ? null
0325: : (Date) certificateValid.clone();
0326: }
0327:
0328: /**
0329: * @com.intel.drl.spec_ref
0330: */
0331: public void setPrivateKeyValid(Date privateKeyValid) {
0332: if (privateKeyValid == null) {
0333: this .privateKeyValid = null;
0334: return;
0335: }
0336: this .privateKeyValid = (Date) privateKeyValid.clone();
0337: }
0338:
0339: /**
0340: * @com.intel.drl.spec_ref
0341: */
0342: public Date getPrivateKeyValid() {
0343: if (privateKeyValid != null) {
0344: return (Date) privateKeyValid.clone();
0345: }
0346: return null;
0347: }
0348:
0349: private void checkOID(String oid) throws IOException {
0350: int beg = 0;
0351: int end = oid.indexOf('.', beg);
0352: try {
0353: int comp = Integer.parseInt(oid.substring(beg, end));
0354: beg = end + 1;
0355: if ((comp < 0) || (comp > 2)) {
0356: throw new IOException(Messages.getString(
0357: "security.56", oid)); //$NON-NLS-1$
0358: }
0359: end = oid.indexOf('.', beg);
0360: comp = Integer.parseInt(oid.substring(beg, end));
0361: if ((comp < 0) || (comp > 39)) {
0362: throw new IOException(Messages.getString(
0363: "security.56", oid)); //$NON-NLS-1$
0364: }
0365: } catch (IndexOutOfBoundsException e) {
0366: throw new IOException(Messages
0367: .getString("security.56", oid)); //$NON-NLS-1$
0368: } catch (NumberFormatException e) {
0369: throw new IOException(Messages
0370: .getString("security.56", oid)); //$NON-NLS-1$
0371: }
0372: }
0373:
0374: /**
0375: * @com.intel.drl.spec_ref
0376: */
0377: public void setSubjectPublicKeyAlgID(String oid) throws IOException {
0378: if (oid == null) {
0379: subjectPublicKeyAlgID = null;
0380: return;
0381: }
0382: checkOID(oid);
0383: subjectPublicKeyAlgID = oid;
0384: }
0385:
0386: /**
0387: * @com.intel.drl.spec_ref
0388: */
0389: public String getSubjectPublicKeyAlgID() {
0390: return subjectPublicKeyAlgID;
0391: }
0392:
0393: /**
0394: * @com.intel.drl.spec_ref
0395: */
0396: public void setSubjectPublicKey(PublicKey key) {
0397: subjectPublicKey = (key == null) ? null : key.getEncoded();
0398: subjectPublicKeyImpl = key;
0399: }
0400:
0401: /**
0402: * @com.intel.drl.spec_ref
0403: */
0404: public void setSubjectPublicKey(byte[] key) throws IOException {
0405: if (key == null) {
0406: subjectPublicKey = null;
0407: subjectPublicKeyImpl = null;
0408: return;
0409: }
0410: subjectPublicKey = new byte[key.length];
0411: System.arraycopy(key, 0, subjectPublicKey, 0, key.length);
0412: subjectPublicKeyImpl = ((SubjectPublicKeyInfo) SubjectPublicKeyInfo.ASN1
0413: .decode(key)).getPublicKey();
0414: }
0415:
0416: /**
0417: * @com.intel.drl.spec_ref
0418: */
0419: public PublicKey getSubjectPublicKey() {
0420: return subjectPublicKeyImpl;
0421: }
0422:
0423: /**
0424: * @com.intel.drl.spec_ref
0425: */
0426: public void setKeyUsage(boolean[] keyUsage) {
0427: if (keyUsage == null) {
0428: this .keyUsage = null;
0429: return;
0430: }
0431: this .keyUsage = new boolean[keyUsage.length];
0432: System
0433: .arraycopy(keyUsage, 0, this .keyUsage, 0,
0434: keyUsage.length);
0435: }
0436:
0437: /**
0438: * @com.intel.drl.spec_ref
0439: */
0440: public boolean[] getKeyUsage() {
0441: if (keyUsage == null) {
0442: return null;
0443: }
0444: boolean[] result = new boolean[keyUsage.length];
0445: System.arraycopy(keyUsage, 0, result, 0, keyUsage.length);
0446: return result;
0447: }
0448:
0449: /**
0450: * @com.intel.drl.spec_ref
0451: */
0452: public void setExtendedKeyUsage(Set<String> keyUsage)
0453: throws IOException {
0454: extendedKeyUsage = null;
0455: if ((keyUsage == null) || (keyUsage.size() == 0)) {
0456: return;
0457: }
0458: HashSet key_u = new HashSet();
0459: Iterator it = keyUsage.iterator();
0460: while (it.hasNext()) {
0461: String usage = (String) it.next();
0462: checkOID(usage);
0463: key_u.add(usage);
0464: }
0465: extendedKeyUsage = Collections.unmodifiableSet(key_u);
0466: }
0467:
0468: /**
0469: * @com.intel.drl.spec_ref
0470: */
0471: public Set<String> getExtendedKeyUsage() {
0472: return extendedKeyUsage;
0473: }
0474:
0475: /**
0476: * @com.intel.drl.spec_ref
0477: */
0478: public void setMatchAllSubjectAltNames(boolean matchAllNames) {
0479: this .matchAllNames = matchAllNames;
0480: }
0481:
0482: /**
0483: * @com.intel.drl.spec_ref
0484: */
0485: public boolean getMatchAllSubjectAltNames() {
0486: return matchAllNames;
0487: }
0488:
0489: /**
0490: * @com.intel.drl.spec_ref
0491: */
0492: public void setSubjectAlternativeNames(Collection<List<?>> names)
0493: throws IOException {
0494: subjectAltNames = null;
0495: if ((names == null) || (names.size() == 0)) {
0496: return;
0497: }
0498: Iterator it = names.iterator();
0499: while (it.hasNext()) {
0500: List name = (List) it.next();
0501: int tag = ((Integer) name.get(0)).intValue();
0502: Object value = name.get(1);
0503: if (value instanceof String) {
0504: addSubjectAlternativeName(tag, (String) value);
0505: } else if (value instanceof byte[]) {
0506: addSubjectAlternativeName(tag, (byte[]) value);
0507: } else {
0508: throw new IOException(Messages.getString("security.57")); //$NON-NLS-1$
0509: }
0510: }
0511: }
0512:
0513: /**
0514: * @com.intel.drl.spec_ref
0515: */
0516: public void addSubjectAlternativeName(int tag, String name)
0517: throws IOException {
0518: GeneralName alt_name = new GeneralName(tag, name);
0519: // create only if there was not any errors
0520: if (subjectAltNames == null) {
0521: subjectAltNames = new ArrayList[9];
0522: }
0523: if (subjectAltNames[tag] == null) {
0524: subjectAltNames[tag] = new ArrayList();
0525: }
0526: subjectAltNames[tag].add(alt_name);
0527: }
0528:
0529: /**
0530: * @com.intel.drl.spec_ref
0531: */
0532: public void addSubjectAlternativeName(int tag, byte[] name)
0533: throws IOException {
0534: GeneralName alt_name = new GeneralName(tag, name);
0535: // create only if there was not any errors
0536: if (subjectAltNames == null) {
0537: subjectAltNames = new ArrayList[9];
0538: }
0539: if (subjectAltNames[tag] == null) {
0540: subjectAltNames[tag] = new ArrayList();
0541: }
0542: subjectAltNames[tag].add(alt_name);
0543: }
0544:
0545: /**
0546: * @com.intel.drl.spec_ref
0547: */
0548: public Collection<List<?>> getSubjectAlternativeNames() {
0549: if (subjectAltNames == null) {
0550: return null;
0551: }
0552: ArrayList result = new ArrayList();
0553: for (int tag = 0; tag < 9; tag++) {
0554: if (subjectAltNames[tag] != null) {
0555: Integer teg = new Integer(tag);
0556: for (int name = 0; name < subjectAltNames[tag].size(); name++) {
0557: Object neim = subjectAltNames[tag].get(name);
0558: if (neim instanceof byte[]) {
0559: byte[] arr_neim = (byte[]) neim;
0560: neim = new byte[arr_neim.length];
0561: System.arraycopy(arr_neim, 0, neim, 0,
0562: arr_neim.length);
0563: }
0564: List list = new ArrayList(2);
0565: list.add(teg);
0566: list.add(neim);
0567: result.add(list);
0568: }
0569: }
0570: }
0571: return result;
0572: }
0573:
0574: /**
0575: * @com.intel.drl.spec_ref
0576: */
0577: public void setNameConstraints(byte[] bytes) throws IOException {
0578: this .nameConstraints = (bytes == null) ? null
0579: : (NameConstraints) NameConstraints.ASN1.decode(bytes);
0580: }
0581:
0582: /**
0583: * @com.intel.drl.spec_ref
0584: */
0585: public byte[] getNameConstraints() {
0586: return (nameConstraints == null) ? null : nameConstraints
0587: .getEncoded();
0588: }
0589:
0590: /**
0591: * @com.intel.drl.spec_ref
0592: */
0593: public void setBasicConstraints(int pathLen) {
0594: if (pathLen < -2) {
0595: throw new IllegalArgumentException(Messages
0596: .getString("security.58")); //$NON-NLS-1$
0597: }
0598: this .pathLen = pathLen;
0599: }
0600:
0601: /**
0602: * @com.intel.drl.spec_ref
0603: */
0604: public int getBasicConstraints() {
0605: return pathLen;
0606: }
0607:
0608: /**
0609: * @com.intel.drl.spec_ref
0610: */
0611: public void setPolicy(Set<String> policies) throws IOException {
0612: if (policies == null) {
0613: this .policies = null;
0614: return;
0615: }
0616: HashSet pols = new HashSet(policies.size());
0617: Iterator it = policies.iterator();
0618: while (it.hasNext()) {
0619: String certPolicyId = (String) it.next();
0620: checkOID(certPolicyId);
0621: pols.add(certPolicyId);
0622: }
0623: this .policies = Collections.unmodifiableSet(pols);
0624: }
0625:
0626: /**
0627: * @com.intel.drl.spec_ref
0628: */
0629: public Set<String> getPolicy() {
0630: return policies;
0631: }
0632:
0633: /**
0634: * @com.intel.drl.spec_ref
0635: */
0636: public void setPathToNames(Collection<List<?>> names)
0637: throws IOException {
0638: pathToNames = null;
0639: if ((names == null) || (names.size() == 0)) {
0640: return;
0641: }
0642: Iterator it = names.iterator();
0643: while (it.hasNext()) {
0644: List name = (List) it.next();
0645: int tag = ((Integer) name.get(0)).intValue();
0646: Object value = name.get(1);
0647: if (value instanceof String) {
0648: addPathToName(tag, (String) value);
0649: } else if (value instanceof byte[]) {
0650: addPathToName(tag, (byte[]) value);
0651: } else {
0652: throw new IOException(Messages.getString("security.57")); //$NON-NLS-1$
0653: }
0654: }
0655: }
0656:
0657: /**
0658: * @com.intel.drl.spec_ref
0659: */
0660: public void addPathToName(int type, String name) throws IOException {
0661: GeneralName path_name = new GeneralName(type, name);
0662: // create only if there was not any errors
0663: if (pathToNames == null) {
0664: pathToNames = new ArrayList();
0665: }
0666: pathToNames.add(path_name);
0667: }
0668:
0669: /**
0670: * @com.intel.drl.spec_ref
0671: */
0672: public void addPathToName(int type, byte[] name) throws IOException {
0673: GeneralName path_name = new GeneralName(type, name);
0674: // create only if there was not any errors
0675: if (pathToNames == null) {
0676: pathToNames = new ArrayList();
0677: }
0678: pathToNames.add(path_name);
0679: }
0680:
0681: /**
0682: * @com.intel.drl.spec_ref
0683: */
0684: public Collection<List<?>> getPathToNames() {
0685: if (pathToNames == null) {
0686: return null;
0687: }
0688: ArrayList result = new ArrayList();
0689: Iterator it = pathToNames.iterator();
0690: while (it.hasNext()) {
0691: GeneralName name = (GeneralName) it.next();
0692: result.add(name.getAsList());
0693: }
0694: return result;
0695: }
0696:
0697: /**
0698: * @com.intel.drl.spec_ref
0699: */
0700: public String toString() {
0701: // For convenient reading of the string representation
0702: // all of the fields named according to the rfc 3280
0703: // (http://www.ietf.org/rfc/rfc3280.txt).
0704:
0705: StringBuffer result = new StringBuffer();
0706: result.append("X509CertSelector: \n["); //$NON-NLS-1$
0707: if (this .certificateEquals != null) {
0708: result
0709: .append("\n certificateEquals: " + certificateEquals); //$NON-NLS-1$
0710: }
0711: if (this .serialNumber != null) {
0712: //FIXME: needs DRL's BigInteger.toString implementation
0713: //result.append("\n serialNumber: " + serialNumber);
0714: }
0715: if (this .issuer != null) {
0716: result.append("\n issuer: " + issuer); //$NON-NLS-1$
0717: }
0718: if (this .subject != null) {
0719: result.append("\n subject: " + subject); //$NON-NLS-1$
0720: }
0721: if (this .subjectKeyIdentifier != null) {
0722: result.append("\n subjectKeyIdentifier: " //$NON-NLS-1$
0723: + getBytesAsString(subjectKeyIdentifier));
0724: }
0725: if (this .authorityKeyIdentifier != null) {
0726: result.append("\n authorityKeyIdentifier: " //$NON-NLS-1$
0727: + getBytesAsString(authorityKeyIdentifier));
0728: }
0729: if (this .certificateValid != null) {
0730: result.append("\n certificateValid: " + certificateValid); //$NON-NLS-1$
0731: }
0732: if (this .subjectPublicKeyAlgID != null) {
0733: result.append("\n subjectPublicKeyAlgID: " //$NON-NLS-1$
0734: + subjectPublicKeyAlgID);
0735: }
0736: if (this .privateKeyValid != null) {
0737: result.append("\n privateKeyValid: " + privateKeyValid); //$NON-NLS-1$
0738: }
0739: if (this .subjectPublicKey != null) {
0740: result.append("\n subjectPublicKey: " //$NON-NLS-1$
0741: + getBytesAsString(subjectPublicKey));
0742: }
0743: if (this .keyUsage != null) {
0744: result.append("\n keyUsage: \n ["); //$NON-NLS-1$
0745: String[] kuNames = new String[] {
0746: "digitalSignature", "nonRepudiation", "keyEncipherment", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
0747: "dataEncipherment", "keyAgreement", "keyCertSign", "cRLSign", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
0748: "encipherOnly", "decipherOnly" //$NON-NLS-1$ //$NON-NLS-2$
0749: };
0750: for (int i = 0; i < 9; i++) {
0751: if (keyUsage[i]) {
0752: result.append("\n " + kuNames[i]); //$NON-NLS-1$
0753: }
0754: }
0755: result.append("\n ]"); //$NON-NLS-1$
0756: }
0757: if (this .extendedKeyUsage != null) {
0758: result.append("\n extendedKeyUsage: " //$NON-NLS-1$
0759: + extendedKeyUsage.toString());
0760: }
0761: result.append("\n matchAllNames: " + matchAllNames); //$NON-NLS-1$
0762: result.append("\n pathLen: " + pathLen); //$NON-NLS-1$
0763: if (this .subjectAltNames != null) {
0764: result.append("\n subjectAltNames: \n ["); //$NON-NLS-1$
0765: for (int i = 0; i < 9; i++) {
0766: List names = this .subjectAltNames[i];
0767: if (names != null) {
0768: int size = names.size();
0769: for (int j = 0; j < size; j++) {
0770: result.append("\n " //$NON-NLS-1$
0771: + ((GeneralName) names.get(j))
0772: .toString());
0773: }
0774: }
0775: }
0776: result.append("\n ]"); //$NON-NLS-1$
0777: }
0778: if (this .nameConstraints != null) {
0779: }
0780: if (this .policies != null) {
0781: result.append("\n policies: " + policies.toString()); //$NON-NLS-1$
0782: }
0783: if (this .pathToNames != null) {
0784: result.append("\n pathToNames: \n ["); //$NON-NLS-1$
0785: int size = pathToNames.size();
0786: for (int i = 0; i < size; i++) {
0787: result
0788: .append("\n " //$NON-NLS-1$
0789: + ((GeneralName) pathToNames.get(i))
0790: .toString());
0791: }
0792: }
0793: result.append("\n]"); //$NON-NLS-1$
0794: return result.toString();
0795: }
0796:
0797: private String getBytesAsString(byte[] data) {
0798: String result = ""; //$NON-NLS-1$
0799: for (int i = 0; i < data.length; i++) {
0800: String tail = Integer.toHexString(0x00ff & data[i]);
0801: if (tail.length() == 1) {
0802: tail = "0" + tail; //$NON-NLS-1$
0803: }
0804: result += tail + " "; //$NON-NLS-1$
0805: }
0806: return result;
0807: }
0808:
0809: private byte[] getExtensionValue(X509Certificate cert, String oid) {
0810: try {
0811: byte[] bytes = cert.getExtensionValue(oid);
0812: if (bytes == null) {
0813: return null;
0814: }
0815: return (byte[]) ASN1OctetString.getInstance().decode(bytes);
0816: } catch (IOException e) {
0817: return null;
0818: }
0819: }
0820:
0821: /**
0822: * @com.intel.drl.spec_ref
0823: */
0824: public boolean match(Certificate certificate) {
0825: if (!(certificate instanceof X509Certificate)) {
0826: return false;
0827: }
0828:
0829: X509Certificate cert = (X509Certificate) certificate;
0830: if ((certificateEquals != null)
0831: && !certificateEquals.equals(cert)) {
0832: return false;
0833: }
0834: if ((serialNumber != null)
0835: && !serialNumber.equals(cert.getSerialNumber())) {
0836: return false;
0837: }
0838: if ((issuer != null)
0839: && !issuer.equals(cert.getIssuerX500Principal())) {
0840: return false;
0841: }
0842: if ((subject != null)
0843: && !subject.equals(cert.getSubjectX500Principal())) {
0844: return false;
0845: }
0846: if ((subjectKeyIdentifier != null)
0847: && !Arrays.equals(subjectKeyIdentifier,
0848: // Here and later all of the extension OIDs
0849: // are taken from rfc 3280 (http://www.ietf.org/rfc/rfc3280.txt)
0850: getExtensionValue(cert, "2.5.29.14"))) { //$NON-NLS-1$
0851: return false;
0852: }
0853: if ((authorityKeyIdentifier != null)
0854: && !Arrays.equals(authorityKeyIdentifier,
0855: getExtensionValue(cert, "2.5.29.35"))) { //$NON-NLS-1$
0856: return false;
0857: }
0858: if (certificateValid != null) {
0859: try {
0860: cert.checkValidity(certificateValid);
0861: } catch (CertificateExpiredException e) {
0862: return false;
0863: } catch (CertificateNotYetValidException e) {
0864: return false;
0865: }
0866: }
0867: if (privateKeyValid != null) {
0868: try {
0869: byte[] bytes = getExtensionValue(cert, "2.5.29.16"); //$NON-NLS-1$
0870: if (bytes == null) {
0871: return false;
0872: }
0873: PrivateKeyUsagePeriod pkup = (PrivateKeyUsagePeriod) PrivateKeyUsagePeriod.ASN1
0874: .decode(bytes);
0875: Date notBefore = pkup.getNotBefore();
0876: Date notAfter = pkup.getNotAfter();
0877: if ((notBefore == null) && (notAfter == null)) {
0878: return false;
0879: }
0880: if ((notBefore != null)
0881: && notBefore.compareTo(privateKeyValid) > 0) {
0882: return false;
0883: }
0884: if ((notAfter != null)
0885: && notAfter.compareTo(privateKeyValid) < 0) {
0886: return false;
0887: }
0888: } catch (IOException e) {
0889: return false;
0890: }
0891: }
0892: if (subjectPublicKeyAlgID != null) {
0893: try {
0894: byte[] encoding = cert.getPublicKey().getEncoded();
0895: AlgorithmIdentifier ai = ((SubjectPublicKeyInfo) SubjectPublicKeyInfo.ASN1
0896: .decode(encoding)).getAlgorithmIdentifier();
0897: if (!subjectPublicKeyAlgID.equals(ai.getAlgorithm())) {
0898: return false;
0899: }
0900: } catch (IOException e) {
0901: e.printStackTrace();
0902: return false;
0903: }
0904: }
0905: if (subjectPublicKey != null) {
0906: if (!Arrays.equals(subjectPublicKey, cert.getPublicKey()
0907: .getEncoded())) {
0908: return false;
0909: }
0910: }
0911: if (keyUsage != null) {
0912: boolean[] ku = cert.getKeyUsage();
0913: if (ku != null) {
0914: int i = 0;
0915: int min_length = (ku.length < keyUsage.length) ? ku.length
0916: : keyUsage.length;
0917: for (; i < min_length; i++) {
0918: if (keyUsage[i] && !ku[i]) {
0919: // the specified keyUsage allows,
0920: // but certificate does not.
0921: return false;
0922: }
0923: }
0924: for (; i < keyUsage.length; i++) {
0925: if (keyUsage[i]) {
0926: return false;
0927: }
0928: }
0929: }
0930: }
0931: if (extendedKeyUsage != null) {
0932: try {
0933: List keyUsage = cert.getExtendedKeyUsage();
0934: if (keyUsage != null) {
0935: if (!keyUsage.containsAll(extendedKeyUsage)) {
0936: return false;
0937: }
0938: }
0939: } catch (CertificateParsingException e) {
0940: return false;
0941: }
0942: }
0943: if (pathLen != -1) {
0944: int p_len = cert.getBasicConstraints();
0945: if ((pathLen < 0) && (p_len >= 0)) {
0946: // need end-entity but got CA
0947: return false;
0948: }
0949: if ((pathLen > 0) && (pathLen > p_len)) {
0950: // allowed _pathLen is small
0951: return false;
0952: }
0953: }
0954: if (subjectAltNames != null) {
0955: PASSED: try {
0956: byte[] bytes = getExtensionValue(cert, "2.5.29.17"); //$NON-NLS-1$
0957: if (bytes == null) {
0958: return false;
0959: }
0960: List sans = ((GeneralNames) GeneralNames.ASN1
0961: .decode(bytes)).getNames();
0962: if ((sans == null) || (sans.size() == 0)) {
0963: return false;
0964: }
0965: boolean[][] map = new boolean[9][];
0966: // initialize the check map
0967: for (int i = 0; i < 9; i++) {
0968: map[i] = (subjectAltNames[i] == null) ? new boolean[0]
0969: : new boolean[subjectAltNames[i].size()];
0970: }
0971: Iterator it = sans.iterator();
0972: while (it.hasNext()) {
0973: GeneralName name = (GeneralName) it.next();
0974: int tag = name.getTag();
0975: for (int i = 0; i < map[tag].length; i++) {
0976: if (((GeneralName) subjectAltNames[tag].get(i))
0977: .equals(name)) {
0978: if (!matchAllNames) {
0979: break PASSED;
0980: }
0981: map[tag][i] = true;
0982: }
0983: }
0984: }
0985: if (!matchAllNames) {
0986: // there was not any match
0987: return false;
0988: }
0989: // else check the map
0990: for (int tag = 0; tag < 9; tag++) {
0991: for (int name = 0; name < map[tag].length; name++) {
0992: if (!map[tag][name]) {
0993: return false;
0994: }
0995: }
0996: }
0997: } catch (IOException e) {
0998: e.printStackTrace();
0999: return false;
1000: }
1001: }
1002: if (nameConstraints != null) {
1003: if (!nameConstraints.isAcceptable(cert)) {
1004: return false;
1005: }
1006: }
1007: if (policies != null) {
1008: byte[] bytes = getExtensionValue(cert, "2.5.29.32"); //$NON-NLS-1$
1009: if (bytes == null) {
1010: return false;
1011: }
1012: if (policies.size() == 0) {
1013: // if certificate has such extension than it has at least
1014: // one policy in it.
1015: return true;
1016: }
1017: PASSED: try {
1018: List policyInformations = ((CertificatePolicies) CertificatePolicies.ASN1
1019: .decode(bytes)).getPolicyInformations();
1020: Iterator it = policyInformations.iterator();
1021: while (it.hasNext()) {
1022: if (policies.contains(((PolicyInformation) it
1023: .next()).getPolicyIdentifier())) {
1024: break PASSED;
1025: }
1026: }
1027: return false;
1028: } catch (IOException e) {
1029: // the extension is invalid
1030: return false;
1031: }
1032: }
1033: if (pathToNames != null) {
1034: byte[] bytes = getExtensionValue(cert, "2.5.29.30"); //$NON-NLS-1$
1035: if (bytes != null) {
1036: NameConstraints nameConstraints;
1037: try {
1038: nameConstraints = (NameConstraints) NameConstraints.ASN1
1039: .decode(bytes);
1040: } catch (IOException e) {
1041: // the extension is invalid;
1042: return false;
1043: }
1044: if (!nameConstraints.isAcceptable(pathToNames)) {
1045: return false;
1046: }
1047: }
1048: }
1049: return true;
1050: }
1051:
1052: /**
1053: * @com.intel.drl.spec_ref
1054: */
1055: public Object clone() {
1056: X509CertSelector result;
1057:
1058: try {
1059: result = (X509CertSelector) super .clone();
1060: } catch (CloneNotSupportedException e) {
1061: return null;
1062: }
1063:
1064: if (this .subjectKeyIdentifier != null) {
1065: result.subjectKeyIdentifier = new byte[this .subjectKeyIdentifier.length];
1066: System.arraycopy(this .subjectKeyIdentifier, 0,
1067: result.subjectKeyIdentifier, 0,
1068: this .subjectKeyIdentifier.length);
1069: }
1070: if (this .authorityKeyIdentifier != null) {
1071: result.authorityKeyIdentifier = new byte[this .authorityKeyIdentifier.length];
1072: System.arraycopy(this .authorityKeyIdentifier, 0,
1073: result.authorityKeyIdentifier, 0,
1074: this .authorityKeyIdentifier.length);
1075: }
1076: if (this .subjectPublicKey != null) {
1077: result.subjectPublicKey = new byte[this .subjectPublicKey.length];
1078: System.arraycopy(this .subjectPublicKey, 0,
1079: result.subjectPublicKey, 0,
1080: this .subjectPublicKey.length);
1081: }
1082: if (this .keyUsage != null) {
1083: result.keyUsage = new boolean[this .keyUsage.length];
1084: System.arraycopy(this .keyUsage, 0, result.keyUsage, 0,
1085: this .keyUsage.length);
1086: }
1087: result.extendedKeyUsage = (this .extendedKeyUsage == null) ? null
1088: : new HashSet(this .extendedKeyUsage);
1089: if (this .subjectAltNames != null) {
1090: result.subjectAltNames = new ArrayList[9];
1091: for (int i = 0; i < 9; i++) {
1092: if (this .subjectAltNames[i] != null) {
1093: result.subjectAltNames[i] = new ArrayList(
1094: this .subjectAltNames[i]);
1095: }
1096: }
1097: }
1098: result.policies = (this .policies == null) ? null : new HashSet(
1099: this .policies);
1100: result.pathToNames = (this .pathToNames == null) ? null
1101: : new ArrayList(this.pathToNames);
1102: return result;
1103: }
1104: }
|