use of java.security.PublicKey in project android_frameworks_base by ResurrectionRemix.
the class KeySetManagerServiceTest method testAddSigningKSToPackageSuper.
/*
* add a package which is signed by a keyset which contains a previously seen
* public key and make sure its refernces are incremented.
*/
public void testAddSigningKSToPackageSuper() throws ReflectiveOperationException {
/* create PackageSettings and add to Settings mPackages */
PackageSetting ps1 = generateFakePackageSetting("packageA");
mPackagesMap.put(ps1.name, ps1);
PackageSetting ps2 = generateFakePackageSetting("packageB");
mPackagesMap.put(ps2.name, ps2);
/* collect signing key and add */
ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>();
PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
signingKeys.add(keyA);
mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys);
/* give ps2 a superset (add keyB) */
PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
signingKeys.add(keyB);
mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys);
assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
assertEquals(2, KeySetUtils.getPubKeyRefCount(mKsms, 1));
assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
assertEquals(2, ksMapping.size());
ArraySet<Long> mapping = ksMapping.get(1);
assertEquals(1, mapping.size());
assertTrue(mapping.contains(new Long(1)));
mapping = ksMapping.get(2);
assertEquals(2, mapping.size());
assertTrue(mapping.contains(new Long(1)));
assertTrue(mapping.contains(new Long(2)));
assertEquals(1, ps1.keySetData.getProperSigningKeySet());
assertEquals(2, ps2.keySetData.getProperSigningKeySet());
}
use of java.security.PublicKey in project android_frameworks_base by ResurrectionRemix.
the class AndroidKeyStoreProvider method getAndroidKeyStorePublicKey.
@NonNull
public static AndroidKeyStorePublicKey getAndroidKeyStorePublicKey(@NonNull String alias, int uid, @NonNull @KeyProperties.KeyAlgorithmEnum String keyAlgorithm, @NonNull byte[] x509EncodedForm) {
PublicKey publicKey;
try {
KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);
publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(x509EncodedForm));
} catch (NoSuchAlgorithmException e) {
throw new ProviderException("Failed to obtain " + keyAlgorithm + " KeyFactory", e);
} catch (InvalidKeySpecException e) {
throw new ProviderException("Invalid X.509 encoding of public key", e);
}
if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
return new AndroidKeyStoreECPublicKey(alias, uid, (ECPublicKey) publicKey);
} else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
return new AndroidKeyStoreRSAPublicKey(alias, uid, (RSAPublicKey) publicKey);
} else {
throw new ProviderException("Unsupported Android Keystore public key algorithm: " + keyAlgorithm);
}
}
use of java.security.PublicKey in project android_frameworks_base by ResurrectionRemix.
the class KeySetManagerService method getIdForPublicKeyLPr.
/**
* Finds the stable identifier for a PublicKey or PUBLIC_KEY_NOT_FOUND.
*/
private long getIdForPublicKeyLPr(PublicKey k) {
String encodedPublicKey = new String(k.getEncoded());
for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) {
PublicKey value = mPublicKeys.valueAt(publicKeyIndex).getKey();
String encodedExistingKey = new String(value.getEncoded());
if (encodedPublicKey.equals(encodedExistingKey)) {
return mPublicKeys.keyAt(publicKeyIndex);
}
}
return PUBLIC_KEY_NOT_FOUND;
}
use of java.security.PublicKey in project android_frameworks_base by ResurrectionRemix.
the class PackageParser method parseVerifier.
private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser, AttributeSet attrs, int flags) {
final TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestPackageVerifier);
final String packageName = sa.getNonResourceString(com.android.internal.R.styleable.AndroidManifestPackageVerifier_name);
final String encodedPublicKey = sa.getNonResourceString(com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey);
sa.recycle();
if (packageName == null || packageName.length() == 0) {
Slog.i(TAG, "verifier package name was null; skipping");
return null;
}
final PublicKey publicKey = parsePublicKey(encodedPublicKey);
if (publicKey == null) {
Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
return null;
}
return new VerifierInfo(packageName, publicKey);
}
use of java.security.PublicKey in project android_frameworks_base by ResurrectionRemix.
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();
}
}
Aggregations