use of sun.security.pkcs.SignerInfo in project android_frameworks_base by AOSPA.
the class RecoverySystem method verifyPackage.
/**
* Verify the cryptographic signature of a system update package
* before installing it. Note that the package is also verified
* separately by the installer once the device is rebooted into
* the recovery system. This function will return only if the
* package was successfully verified; otherwise it will throw an
* exception.
*
* Verification of a package can take significant time, so this
* function should not be called from a UI thread. Interrupting
* the thread while this function is in progress will result in a
* SecurityException being thrown (and the thread's interrupt flag
* will be cleared).
*
* @param packageFile the package to be verified
* @param listener an object to receive periodic progress
* updates as verification proceeds. May be null.
* @param deviceCertsZipFile the zip file of certificates whose
* public keys we will accept. Verification succeeds if the
* package is signed by the private key corresponding to any
* public key in this file. May be null to use the system default
* file (currently "/system/etc/security/otacerts.zip").
*
* @throws IOException if there were any errors reading the
* package or certs files.
* @throws GeneralSecurityException if verification failed
*/
public static void verifyPackage(File packageFile, ProgressListener listener, File deviceCertsZipFile) throws IOException, GeneralSecurityException {
final long fileLen = packageFile.length();
final RandomAccessFile raf = new RandomAccessFile(packageFile, "r");
try {
final long startTimeMillis = System.currentTimeMillis();
if (listener != null) {
listener.onProgress(0);
}
raf.seek(fileLen - 6);
byte[] footer = new byte[6];
raf.readFully(footer);
if (footer[2] != (byte) 0xff || footer[3] != (byte) 0xff) {
throw new SignatureException("no signature in file (no footer)");
}
final int commentSize = (footer[4] & 0xff) | ((footer[5] & 0xff) << 8);
final int signatureStart = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8);
byte[] eocd = new byte[commentSize + 22];
raf.seek(fileLen - (commentSize + 22));
raf.readFully(eocd);
// end-of-central-directory record.
if (eocd[0] != (byte) 0x50 || eocd[1] != (byte) 0x4b || eocd[2] != (byte) 0x05 || eocd[3] != (byte) 0x06) {
throw new SignatureException("no signature in file (bad footer)");
}
for (int i = 4; i < eocd.length - 3; ++i) {
if (eocd[i] == (byte) 0x50 && eocd[i + 1] == (byte) 0x4b && eocd[i + 2] == (byte) 0x05 && eocd[i + 3] == (byte) 0x06) {
throw new SignatureException("EOCD marker found after start of EOCD");
}
}
// Parse the signature
PKCS7 block = new PKCS7(new ByteArrayInputStream(eocd, commentSize + 22 - signatureStart, signatureStart));
// Take the first certificate from the signature (packages
// should contain only one).
X509Certificate[] certificates = block.getCertificates();
if (certificates == null || certificates.length == 0) {
throw new SignatureException("signature contains no certificates");
}
X509Certificate cert = certificates[0];
PublicKey signatureKey = cert.getPublicKey();
SignerInfo[] signerInfos = block.getSignerInfos();
if (signerInfos == null || signerInfos.length == 0) {
throw new SignatureException("signature contains no signedData");
}
SignerInfo signerInfo = signerInfos[0];
// Check that the public key of the certificate contained
// in the package equals one of our trusted public keys.
boolean verified = false;
HashSet<X509Certificate> trusted = getTrustedCerts(deviceCertsZipFile == null ? DEFAULT_KEYSTORE : deviceCertsZipFile);
for (X509Certificate c : trusted) {
if (c.getPublicKey().equals(signatureKey)) {
verified = true;
break;
}
}
if (!verified) {
throw new SignatureException("signature doesn't match any trusted key");
}
// The signature cert matches a trusted key. Now verify that
// the digest in the cert matches the actual file data.
raf.seek(0);
final ProgressListener listenerForInner = listener;
SignerInfo verifyResult = block.verify(signerInfo, new InputStream() {
// The signature covers all of the OTA package except the
// archive comment and its 2-byte length.
long toRead = fileLen - commentSize - 2;
long soFar = 0;
int lastPercent = 0;
long lastPublishTime = startTimeMillis;
@Override
public int read() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (soFar >= toRead) {
return -1;
}
if (Thread.currentThread().isInterrupted()) {
return -1;
}
int size = len;
if (soFar + size > toRead) {
size = (int) (toRead - soFar);
}
int read = raf.read(b, off, size);
soFar += read;
if (listenerForInner != null) {
long now = System.currentTimeMillis();
int p = (int) (soFar * 100 / toRead);
if (p > lastPercent && now - lastPublishTime > PUBLISH_PROGRESS_INTERVAL_MS) {
lastPercent = p;
lastPublishTime = now;
listenerForInner.onProgress(lastPercent);
}
}
return read;
}
});
final boolean interrupted = Thread.interrupted();
if (listener != null) {
listener.onProgress(100);
}
if (interrupted) {
throw new SignatureException("verification was interrupted");
}
if (verifyResult == null) {
throw new SignatureException("signature digest verification failed");
}
} finally {
raf.close();
}
}
use of sun.security.pkcs.SignerInfo in project android_frameworks_base by ResurrectionRemix.
the class StrictJarVerifier method verifyBytes.
/**
* Verifies that the signature computed from {@code sfBytes} matches
* that specified in {@code blockBytes} (which is a PKCS7 block). Returns
* certificates listed in the PKCS7 block. Throws a {@code GeneralSecurityException}
* if something goes wrong during verification.
*/
static Certificate[] verifyBytes(byte[] blockBytes, byte[] sfBytes) throws GeneralSecurityException {
Object obj = null;
try {
obj = Providers.startJarVerification();
PKCS7 block = new PKCS7(blockBytes);
SignerInfo[] verifiedSignerInfos = block.verify(sfBytes);
if ((verifiedSignerInfos == null) || (verifiedSignerInfos.length == 0)) {
throw new GeneralSecurityException("Failed to verify signature: no verified SignerInfos");
}
// Ignore any SignerInfo other than the first one, to be compatible with older Android
// platforms which have been doing this for years. See
// libcore/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
// verifySignature method of older platforms.
SignerInfo verifiedSignerInfo = verifiedSignerInfos[0];
List<X509Certificate> verifiedSignerCertChain = verifiedSignerInfo.getCertificateChain(block);
if (verifiedSignerCertChain == null) {
// Should never happen
throw new GeneralSecurityException("Failed to find verified SignerInfo certificate chain");
} else if (verifiedSignerCertChain.isEmpty()) {
// Should never happen
throw new GeneralSecurityException("Verified SignerInfo certificate chain is emtpy");
}
return verifiedSignerCertChain.toArray(new X509Certificate[verifiedSignerCertChain.size()]);
} catch (IOException e) {
throw new GeneralSecurityException("IO exception verifying jar cert", e);
} finally {
Providers.stopJarVerification(obj);
}
}
use of sun.security.pkcs.SignerInfo in project jdk8u_jdk by JetBrains.
the class SignatureFileVerifier method getSigners.
/**
* Given the PKCS7 block and SignerInfo[], create an array of
* CodeSigner objects. We do this only *once* for a given
* signature block file.
*/
private CodeSigner[] getSigners(SignerInfo[] infos, PKCS7 block) throws IOException, NoSuchAlgorithmException, SignatureException, CertificateException {
ArrayList<CodeSigner> signers = null;
for (int i = 0; i < infos.length; i++) {
SignerInfo info = infos[i];
ArrayList<X509Certificate> chain = info.getCertificateChain(block);
CertPath certChain = certificateFactory.generateCertPath(chain);
if (signers == null) {
signers = new ArrayList<>();
}
// Append the new code signer
signers.add(new CodeSigner(certChain, info.getTimestamp()));
if (debug != null) {
debug.println("Signature Block Certificate: " + chain.get(0));
}
}
if (signers != null) {
return signers.toArray(new CodeSigner[signers.size()]);
} else {
return null;
}
}
use of sun.security.pkcs.SignerInfo in project jdk8u_jdk by JetBrains.
the class SimpleSigner method main.
public static void main(String[] argv) throws Exception {
SignerInfo[] signerInfos = new SignerInfo[9];
SimpleSigner signer1 = new SimpleSigner(null, null, null, null);
signerInfos[8] = signer1.genSignerInfo(data1);
signerInfos[7] = signer1.genSignerInfo(new byte[] {});
signerInfos[6] = signer1.genSignerInfo(data2);
SimpleSigner signer2 = new SimpleSigner(null, null, null, null);
signerInfos[5] = signer2.genSignerInfo(data1);
signerInfos[4] = signer2.genSignerInfo(new byte[] {});
signerInfos[3] = signer2.genSignerInfo(data2);
SimpleSigner signer3 = new SimpleSigner(null, null, null, null);
signerInfos[2] = signer3.genSignerInfo(data1);
signerInfos[1] = signer3.genSignerInfo(new byte[] {});
signerInfos[0] = signer3.genSignerInfo(data2);
ContentInfo contentInfo = new ContentInfo(data1);
AlgorithmId[] algIds = { new AlgorithmId(AlgorithmId.SHA256_oid) };
X509Certificate[] certs = { signer3.getCert(), signer2.getCert(), signer1.getCert() };
PKCS7 pkcs71 = new PKCS7(algIds, contentInfo, certs, signerInfos);
System.out.println("SignerInfos in original.");
printSignerInfos(pkcs71.getSignerInfos());
DerOutputStream out = new DerOutputStream();
pkcs71.encodeSignedData(out);
PKCS7 pkcs72 = new PKCS7(out.toByteArray());
System.out.println("\nSignerInfos read back in:");
printSignerInfos(pkcs72.getSignerInfos());
System.out.println("Verified signers of original:");
SignerInfo[] verifs1 = pkcs71.verify();
System.out.println("Verified signers of after read-in:");
SignerInfo[] verifs2 = pkcs72.verify();
if (verifs1.length != verifs2.length) {
throw new RuntimeException("Length or Original vs read-in " + "should be same");
}
}
use of sun.security.pkcs.SignerInfo in project jdk8u_jdk by JetBrains.
the class NonStandardNames method main.
public static void main(String[] args) throws Exception {
byte[] data = "Hello".getBytes();
X500Name n = new X500Name("cn=Me");
CertAndKeyGen cakg = new CertAndKeyGen("RSA", "SHA256withRSA");
cakg.generate(1024);
X509Certificate cert = cakg.getSelfCertificate(n, 1000);
MessageDigest md = MessageDigest.getInstance("SHA-256");
PKCS9Attributes authed = new PKCS9Attributes(new PKCS9Attribute[] { new PKCS9Attribute(PKCS9Attribute.CONTENT_TYPE_OID, ContentInfo.DATA_OID), new PKCS9Attribute(PKCS9Attribute.MESSAGE_DIGEST_OID, md.digest(data)) });
Signature s = Signature.getInstance("SHA256withRSA");
s.initSign(cakg.getPrivateKey());
s.update(authed.getDerEncoding());
byte[] sig = s.sign();
SignerInfo signerInfo = new SignerInfo(n, cert.getSerialNumber(), AlgorithmId.get("SHA-256"), authed, AlgorithmId.get("SHA256withRSA"), sig, null);
PKCS7 pkcs7 = new PKCS7(new AlgorithmId[] { signerInfo.getDigestAlgorithmId() }, new ContentInfo(data), new X509Certificate[] { cert }, new SignerInfo[] { signerInfo });
if (pkcs7.verify(signerInfo, data) == null) {
throw new Exception("Not verified");
}
}
Aggregations