1 9 package org.eclipse.osgi.internal.verifier; 10 11 import java.io.ByteArrayInputStream ; 12 import java.io.IOException ; 13 import java.math.BigInteger ; 14 import java.security.*; 15 import java.security.cert.*; 16 import java.security.cert.Certificate ; 17 import java.text.DateFormat ; 18 import java.text.ParseException ; 19 import java.text.SimpleDateFormat ; 20 import java.util.*; 21 22 import javax.security.auth.x500.X500Principal ; 23 import org.eclipse.osgi.framework.log.FrameworkLogEntry; 24 import org.eclipse.osgi.internal.provisional.verifier.CertificateChain; 25 import org.eclipse.osgi.internal.provisional.verifier.CertificateTrustAuthority; 26 import org.eclipse.osgi.util.NLS; 27 28 31 public class PKCS7Processor implements CertificateChain, JarVerifierConstant { 32 33 private static CertificateFactory certFact; 34 35 static { 36 try { 37 certFact = CertificateFactory.getInstance("X.509"); } catch (CertificateException e) { 39 SignedBundleHook.log(e.getMessage(), FrameworkLogEntry.ERROR, e); 40 } 41 } 42 43 private String certChain; 44 private Certificate [] certificates; 45 private Certificate [] tsaCertificates; 46 private boolean trusted; 47 48 private Map signedAttrs; 50 51 private Map unsignedAttrs; 53 54 private byte signature[]; 56 private String digestAlgorithm; 57 private String signatureAlgorithm; 58 59 private Certificate signerCert; 60 private Date signingTime; 61 62 String oid2String(int oid[]) { 63 StringBuffer sb = new StringBuffer (); 64 for (int i = 0; i < oid.length; i++) { 65 if (i > 0) 66 sb.append('.'); 67 sb.append(oid[i]); 68 } 69 return sb.toString(); 70 } 71 72 String findEncryption(int encOid[]) throws NoSuchAlgorithmException { 73 if (Arrays.equals(DSA_OID, encOid)) { 74 return "DSA"; } 76 if (Arrays.equals(RSA_OID, encOid)) { 77 return "RSA"; } 79 throw new NoSuchAlgorithmException("No algorithm found for " + oid2String(encOid)); } 81 82 String findDigest(int digestOid[]) throws NoSuchAlgorithmException { 83 if (Arrays.equals(SHA1_OID, digestOid)) { 84 return SHA1_STR; 85 } 86 if (Arrays.equals(MD5_OID, digestOid)) { 87 return MD5_STR; 88 } 89 if (Arrays.equals(MD2_OID, digestOid)) { 90 return MD2_STR; 91 } 92 throw new NoSuchAlgorithmException("No algorithm found for " + oid2String(digestOid)); } 94 95 108 109 public PKCS7Processor(String certChain, boolean trusted, byte[][] certificates, long signingTime) throws CertificateException { 110 this.certChain = certChain; 111 this.trusted = trusted; 112 this.certificates = new Certificate [certificates.length]; 113 for (int i = 0; i < certificates.length; i++) 114 this.certificates[i] = certFact.generateCertificate(new ByteArrayInputStream (certificates[i])); 115 if (signingTime > Long.MIN_VALUE) 116 this.signingTime = new Date(signingTime); 117 } 118 119 public PKCS7Processor(byte pkcs7[], int pkcs7Offset, int pkcs7Length) throws IOException , CertificateException, NoSuchAlgorithmException { 120 121 List certs = null; 123 124 BERProcessor bp = new BERProcessor(pkcs7, pkcs7Offset, pkcs7Length); 125 126 bp = bp.stepInto(); 130 if (!Arrays.equals(bp.getObjId(), SIGNEDDATA_OID)) { 131 throw new IOException ("Not a valid PKCS#7 file"); } 133 134 bp.stepOver(); bp = bp.stepInto(); bp = bp.stepInto(); bp.stepOver(); bp.stepOver(); 141 processEncapContentInfo(bp); 143 144 bp.stepOver(); 145 146 if (bp.classOfTag == BERProcessor.CONTEXTSPECIFIC_TAGCLASS && bp.tag == 0) { 148 certs = processCertificates(bp); 150 } 151 152 if (certs == null || certs.size() < 1) 153 throw new SecurityException ("There are no certificates in the .RSA/.DSA file!"); 155 bp.stepOver(); 157 if (bp.classOfTag == BERProcessor.UNIVERSAL_TAGCLASS && bp.tag == 1) { 158 bp.stepOver(); } 160 161 processSignerInfos(bp, certs); 162 163 certs = constructCertPath(certs, signerCert); 165 166 int numCerts = certs.size(); 168 StringBuffer sb = new StringBuffer (); 169 for (int i = 0; i < numCerts; i++) { 170 X509Certificate x509Cert = ((X509Certificate) certs.get(i)); 171 sb.append(x509Cert.getSubjectDN().getName()); 172 sb.append("; "); } 174 certChain = sb.toString(); 175 176 certificates = (Certificate []) certs.toArray(new Certificate [numCerts]); 178 179 if (null == signingTime) 181 signingTime = PKCS7DateParser.parseDate(this); 182 } 183 184 private void processEncapContentInfo(BERProcessor bp) throws IOException { 185 BERProcessor encapContentBERS = bp.stepInto(); 187 if (Arrays.equals(encapContentBERS.getObjId(), TIMESTAMP_TST_OID)) { 188 189 encapContentBERS.stepOver(); 191 BERProcessor encapContentBERS1 = encapContentBERS.stepInto(); 192 193 byte bytesman[] = encapContentBERS1.getBytes(); 195 BERProcessor eContentStructure = new BERProcessor(bytesman, 0, bytesman.length); 196 197 BERProcessor eContentBER = eContentStructure.stepInto(); 199 int tsaVersion = eContentBER.getIntValue().intValue(); 200 201 if (tsaVersion != 1) { 202 throw new IOException ("Not a version 1 time-stamp token"); } 204 205 eContentBER.stepOver(); 207 208 eContentBER.stepOver(); 210 211 eContentBER.stepOver(); 213 214 eContentBER.stepOver(); 216 217 String dateString = new String (eContentBER.getBytes()); 219 if (!dateString.endsWith("Z")) { throw new IOException ("Wrong dateformat used in time-stamp token"); } 222 223 int dotIndex = dateString.indexOf('.'); 226 StringBuffer dateFormatSB = new StringBuffer ("yyyyMMddHHmmss"); if (dotIndex != -1) { 228 int noS = dateString.indexOf('Z') - 1 - dotIndex; 230 dateFormatSB.append('.'); 231 232 for (int i = 0; i < noS; i++) { 234 dateFormatSB.append('s'); 235 } 236 } 237 dateFormatSB.append("'Z'"); 239 try { 240 DateFormat dateFormt = new SimpleDateFormat (dateFormatSB.toString()); 241 dateFormt.setTimeZone(TimeZone.getTimeZone("GMT")); signingTime = dateFormt.parse(dateString); 243 } catch (ParseException e) { 244 throw new IOException (JarVerifierMessages.PKCS7_Parse_Signing_Time_1); 245 } 246 } 247 } 248 249 private List constructCertPath(List certs, Certificate targetCert) { 250 List certsList = new ArrayList(); 251 certsList.add(targetCert); 252 253 X509Certificate currentCert = (X509Certificate) targetCert; 254 int numIteration = certs.size(); 255 int i = 0; 256 while (i < numIteration) { 257 258 X500Principal subject = currentCert.getSubjectX500Principal(); 259 X500Principal issuer = currentCert.getIssuerX500Principal(); 260 261 if (subject.equals(issuer)) { 262 break; 264 } 265 266 currentCert = null; 267 Iterator itr = certs.iterator(); 268 269 while (itr.hasNext()) { 270 X509Certificate tempCert = (X509Certificate) itr.next(); 271 272 if (tempCert.getSubjectX500Principal().equals(issuer)) { 273 certsList.add(tempCert); 274 currentCert = tempCert; 275 } 276 } 277 278 i++; 279 } 280 281 return certsList; 282 } 283 284 public void validateCerts() throws CertificateExpiredException, CertificateNotYetValidException, InvalidKeyException, SignatureException { 285 if (certificates == null || certificates.length == 0) { 286 throw new SecurityException ("There are no certificates in the signature block file!"); } 288 289 int len = certificates.length; 290 291 for (int i = 0; i < len; i++) { 293 X509Certificate currentX509Cert = (X509Certificate) certificates[i]; 294 295 if (signingTime == null) 296 currentX509Cert.checkValidity(); 297 else 298 currentX509Cert.checkValidity(signingTime); 299 300 try { 301 if (i == len - 1) { 302 if (currentX509Cert.getSubjectDN().equals(currentX509Cert.getIssuerDN())) 303 currentX509Cert.verify(currentX509Cert.getPublicKey()); 304 } else { 305 X509Certificate nextX509Cert = (X509Certificate) certificates[i + 1]; 306 currentX509Cert.verify(nextX509Cert.getPublicKey()); 307 } 308 } catch (NoSuchAlgorithmException e) { 309 SignedBundleHook.log(e.getMessage(), FrameworkLogEntry.ERROR, e); 310 throw new SecurityException (NLS.bind(JarVerifierMessages.No_Such_Algorithm_Excep, new String [] {e.getMessage()})); 311 } catch (NoSuchProviderException e) { 312 SignedBundleHook.log(e.getMessage(), FrameworkLogEntry.ERROR, e); 313 throw new SecurityException (NLS.bind(JarVerifierMessages.No_Such_Provider_Excep, new String [] {e.getMessage()})); 314 } catch (CertificateException e) { 315 SignedBundleHook.log(e.getMessage(), FrameworkLogEntry.ERROR, e); 316 throw new SecurityException (NLS.bind(JarVerifierMessages.Validate_Certs_Certificate_Exception, new String [] {e.getMessage()})); 317 } 318 } 319 } 320 321 private Certificate processSignerInfos(BERProcessor bp, List certs) throws CertificateException, NoSuchAlgorithmException { 322 324 bp = bp.stepInto(); bp = bp.stepInto(); 328 BigInteger signerInfoVersion = bp.getIntValue(); 330 if (signerInfoVersion.intValue() != 1) { 331 throw new CertificateException(JarVerifierMessages.PKCS7_SignerInfo_Version_Not_Supported); 332 } 333 334 bp.stepOver(); 337 BERProcessor issuerAndSN = bp.stepInto(); 339 X500Principal signerIssuer = new X500Principal (new ByteArrayInputStream (issuerAndSN.buffer, issuerAndSN.offset, issuerAndSN.endOffset - issuerAndSN.offset)); 340 issuerAndSN.stepOver(); 341 BigInteger sn = issuerAndSN.getIntValue(); 342 343 Certificate newSignerCert = null; 345 346 Iterator itr = certs.iterator(); 347 while (itr.hasNext()) { 350 X509Certificate cert = (X509Certificate) itr.next(); 351 if (cert.getIssuerX500Principal().equals(signerIssuer) && cert.getSerialNumber().equals(sn)) { 352 newSignerCert = cert; 353 break; 354 } 355 } 356 357 if (newSignerCert == null) 358 throw new CertificateException("Signer certificate not in pkcs7block"); 360 signerCert = newSignerCert; 362 363 bp.stepOver(); 366 BERProcessor digestAlg = bp.stepInto(); 368 digestAlgorithm = findDigest(digestAlg.getObjId()); 369 370 bp.stepOver(); 373 processSignedAttributes(bp); 375 376 BERProcessor encryptionAlg = bp.stepInto(); 378 signatureAlgorithm = findEncryption(encryptionAlg.getObjId()); 379 bp.stepOver(); 381 signature = bp.getBytes(); 383 384 bp.stepOver(); 386 387 processUnsignedAttributes(bp); 389 390 return newSignerCert; 391 } 392 393 private void processUnsignedAttributes(BERProcessor bp) { 394 395 if (bp.classOfTag == BERProcessor.CONTEXTSPECIFIC_TAGCLASS && bp.tag == 1) { 396 397 unsignedAttrs = new HashMap(); 399 400 BERProcessor unsignedAttrsBERS = bp.stepInto(); 403 do { 404 BERProcessor unsignedAttrBER = unsignedAttrsBERS.stepInto(); 407 408 int objID[] = unsignedAttrBER.getObjId(); 410 414 unsignedAttrBER.stepOver(); 416 byte structure[] = unsignedAttrBER.getBytes(); 417 unsignedAttrs.put(objID, structure); 418 unsignedAttrsBERS.stepOver(); 419 } while (!unsignedAttrsBERS.endOfSequence()); 420 } 421 } 422 423 private void processSignedAttributes(BERProcessor bp) { 424 if (bp.classOfTag == BERProcessor.CONTEXTSPECIFIC_TAGCLASS) { 425 426 signedAttrs = new HashMap(); 428 429 BERProcessor signedAttrsBERS = bp.stepInto(); 430 do { 431 BERProcessor signedAttrBER = signedAttrsBERS.stepInto(); 432 int[] signedAttrObjID = signedAttrBER.getObjId(); 433 434 signedAttrBER.stepOver(); 436 437 byte[] signedAttrStructure = signedAttrBER.getBytes(); 438 439 signedAttrs.put(signedAttrObjID, signedAttrStructure); 440 441 signedAttrsBERS.stepOver(); 442 } while (!signedAttrsBERS.endOfSequence()); 443 bp.stepOver(); 444 } 445 } 446 447 450 public Certificate getSigner() { 451 if (certificates == null || certificates.length == 0) 452 return null; 453 return certificates[0]; 454 } 455 456 public Certificate getRoot() { 457 if (certificates == null || certificates.length == 0) 458 return null; 459 return certificates[certificates.length - 1]; 460 } 461 462 public Certificate [] getCertificates() { 463 return certificates; 464 } 465 466 470 public String getChain() { 471 return certChain; 472 } 473 474 478 public boolean isTrusted() { 479 return trusted; 480 } 481 482 public boolean equals(Object obj) { 483 if (!(obj instanceof CertificateChain)) 484 return false; 485 if (certificates == null) 486 return false; 487 CertificateChain chain = (CertificateChain) obj; 488 if((signingTime == null ? chain.getSigningTime() != null : !signingTime.equals(chain.getSigningTime()))) 489 return false; 490 if (trusted != chain.isTrusted() || (certChain == null ? chain.getChain() != null : !certChain.equals(chain.getChain()))) 491 return false; 492 Certificate [] otherCerts = chain.getCertificates(); 493 if (otherCerts == null || certificates.length != otherCerts.length) 494 return false; 495 for (int i = 0; i < certificates.length; i++) 496 if (!certificates[i].equals(otherCerts[i])) 497 return false; 498 return true; 499 } 500 501 public void verifySFSignature(byte data[], int dataOffset, int dataLength) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException { 502 Signature sig = Signature.getInstance(digestAlgorithm + "with" + signatureAlgorithm); sig.initVerify(signerCert.getPublicKey()); 504 sig.update(data, dataOffset, dataLength); 505 if (!sig.verify(signature)) { 506 throw new SignatureException(JarVerifierMessages.Signature_Not_Verify); 507 } 508 } 509 510 515 public Map getUnsignedAttrs() { 516 return unsignedAttrs; 517 } 518 519 524 public Map getSignedAttrs() { 525 return signedAttrs; 526 } 527 528 535 private List processCertificates(BERProcessor bp) throws CertificateException { 536 List rtvList = new ArrayList(3); 537 538 BERProcessor certsBERS = bp.stepInto(); 540 541 do { 542 X509Certificate x509Cert = (X509Certificate) certFact.generateCertificate(new ByteArrayInputStream (certsBERS.buffer, certsBERS.offset, certsBERS.endOffset - certsBERS.offset)); 543 544 if (x509Cert != null) { 545 rtvList.add(x509Cert); 546 } 547 548 certsBERS.stepOver(); 550 } while (!certsBERS.endOfSequence()); 551 552 return rtvList; 554 } 555 556 void determineTrust(CertificateTrustAuthority certsTrust) { 557 try { 558 certsTrust.checkTrust(certificates); 559 if (null != tsaCertificates) { 560 certsTrust.checkTrust(tsaCertificates); 561 } 562 trusted = true; 563 } catch (CertificateException e) { 564 trusted = false; 565 } 566 } 567 568 public Date getSigningTime() { 569 return signingTime; 570 } 571 572 void setTSACertificates(Certificate [] tsaCertificates) { 573 this.tsaCertificates = tsaCertificates; 574 } 575 576 587 } | Popular Tags |