From 194523303fd3a11f7a36f0312a4ce1605557be67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sun, 13 Apr 2014 17:46:39 +0200 Subject: Remove unused blob classes and other dead code --- OpenKeychain/src/main/AndroidManifest.xml | 29 +- .../sufficientlysecure/keychain/pgp/PgpToX509.java | 314 --------------------- .../keychain/provider/KeychainContract.java | 14 - .../keychain/provider/KeychainDatabase.java | 17 +- .../keychain/provider/KeychainProvider.java | 18 +- .../provider/KeychainServiceBlobContract.java | 40 --- .../provider/KeychainServiceBlobDatabase.java | 47 --- .../provider/KeychainServiceBlobProvider.java | 162 ----------- .../keychain/remote/OpenPgpService.java | 2 +- .../keychain/remote/RemoteService.java | 15 + .../remote/WrongPackageSignatureException.java | 27 -- .../keychain/util/PausableThreadPoolExecutor.java | 94 ------ .../src/main/java/PgpToX509.java | 314 +++++++++++++++++++++ 13 files changed, 344 insertions(+), 749 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpToX509.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobContract.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobDatabase.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobProvider.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/WrongPackageSignatureException.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/PausableThreadPoolExecutor.java create mode 100644 Resources/old extended service/src/main/java/PgpToX509.java diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index de17f9b20..9c890c3ae 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ - - - + android:process=":remote_api" + tools:ignore="ExportedService"> - - - - - - - - - - - - - - - - diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpToX509.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpToX509.java deleted file mode 100644 index d83575bad..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpToX509.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (C) 2012-2014 Dominik Schürmann - * Copyright (C) 2010-2014 Thialfihar - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.pgp; - -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.x509.AuthorityKeyIdentifier; -import org.spongycastle.asn1.x509.BasicConstraints; -import org.spongycastle.asn1.x509.GeneralName; -import org.spongycastle.asn1.x509.GeneralNames; -import org.spongycastle.asn1.x509.SubjectKeyIdentifier; -import org.spongycastle.asn1.x509.X509Extensions; -import org.spongycastle.asn1.x509.X509Name; -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPPrivateKey; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.x509.X509V3CertificateGenerator; -import org.spongycastle.x509.extension.AuthorityKeyIdentifierStructure; -import org.spongycastle.x509.extension.SubjectKeyIdentifierStructure; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.util.Log; - -import java.io.IOException; -import java.math.BigInteger; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.SignatureException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.text.DateFormat; -import java.util.Date; -import java.util.Iterator; -import java.util.Vector; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.callback.UnsupportedCallbackException; - -public class PgpToX509 { - public static final String DN_COMMON_PART_O = "OpenPGP to X.509 Bridge"; - public static final String DN_COMMON_PART_OU = "OpenPGP Keychain cert"; - - /** - * Creates a self-signed certificate from a public and private key. The (critical) key-usage - * extension is set up with: digital signature, non-repudiation, key-encipherment, key-agreement - * and certificate-signing. The (non-critical) Netscape extension is set up with: SSL client and - * S/MIME. A URI subjectAltName may also be set up. - * - * @param pubKey public key - * @param privKey private key - * @param subject subject (and issuer) DN for this certificate, RFC 2253 format preferred. - * @param startDate date from which the certificate will be valid (defaults to current date and time - * if null) - * @param endDate date until which the certificate will be valid (defaults to current date and time - * if null) * - * @param subjAltNameURI URI to be placed in subjectAltName - * @return self-signed certificate - * @throws InvalidKeyException - * @throws SignatureException - * @throws NoSuchAlgorithmException - * @throws IllegalStateException - * @throws NoSuchProviderException - * @throws CertificateException - * @throws Exception - * @author Bruno Harbulot - */ - public static X509Certificate createSelfSignedCert( - PublicKey pubKey, PrivateKey privKey, X509Name subject, Date startDate, Date endDate, - String subjAltNameURI) - throws InvalidKeyException, IllegalStateException, NoSuchAlgorithmException, - SignatureException, CertificateException, NoSuchProviderException { - - X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator(); - - certGenerator.reset(); - /* - * Sets up the subject distinguished name. Since it's a self-signed certificate, issuer and - * subject are the same. - */ - certGenerator.setIssuerDN(subject); - certGenerator.setSubjectDN(subject); - - /* - * Sets up the validity dates. - */ - if (startDate == null) { - startDate = new Date(System.currentTimeMillis()); - } - certGenerator.setNotBefore(startDate); - if (endDate == null) { - endDate = new Date(startDate.getTime() + (365L * 24L * 60L * 60L * 1000L)); - Log.d(Constants.TAG, "end date is=" + DateFormat.getDateInstance().format(endDate)); - } - - certGenerator.setNotAfter(endDate); - - /* - * The serial-number of this certificate is 1. It makes sense because it's self-signed. - */ - certGenerator.setSerialNumber(BigInteger.ONE); - /* - * Sets the public-key to embed in this certificate. - */ - certGenerator.setPublicKey(pubKey); - /* - * Sets the signature algorithm. - */ - String pubKeyAlgorithm = pubKey.getAlgorithm(); - if (pubKeyAlgorithm.equals("DSA")) { - certGenerator.setSignatureAlgorithm("SHA1WithDSA"); - } else if (pubKeyAlgorithm.equals("RSA")) { - certGenerator.setSignatureAlgorithm("SHA1WithRSAEncryption"); - } else { - RuntimeException re = new RuntimeException("Algorithm not recognised: " - + pubKeyAlgorithm); - Log.e(Constants.TAG, re.getMessage(), re); - throw re; - } - - /* - * Adds the Basic Constraint (CA: true) extension. - */ - certGenerator.addExtension(X509Extensions.BasicConstraints, true, - new BasicConstraints(true)); - - /* - * Adds the subject key identifier extension. - */ - SubjectKeyIdentifier subjectKeyIdentifier = new SubjectKeyIdentifierStructure(pubKey); - certGenerator - .addExtension(X509Extensions.SubjectKeyIdentifier, false, subjectKeyIdentifier); - - /* - * Adds the authority key identifier extension. - */ - AuthorityKeyIdentifier authorityKeyIdentifier = new AuthorityKeyIdentifierStructure(pubKey); - certGenerator.addExtension(X509Extensions.AuthorityKeyIdentifier, false, - authorityKeyIdentifier); - - /* - * Adds the subject alternative-name extension. - */ - if (subjAltNameURI != null) { - GeneralNames subjectAltNames = new GeneralNames(new GeneralName( - GeneralName.uniformResourceIdentifier, subjAltNameURI)); - certGenerator.addExtension(X509Extensions.SubjectAlternativeName, false, - subjectAltNames); - } - - /* - * Creates and sign this certificate with the private key corresponding to the public key of - * the certificate (hence the name "self-signed certificate"). - */ - X509Certificate cert = certGenerator.generate(privKey); - - /* - * Checks that this certificate has indeed been correctly signed. - */ - cert.verify(pubKey); - - return cert; - } - - /** - * Creates a self-signed certificate from a PGP Secret Key. - * - * @param pgpSecKey PGP Secret Key (from which one can extract the public and private - * keys and other attributes). - * @param pgpPrivKey PGP Private Key corresponding to the Secret Key (password callbacks - * should be done before calling this method) - * @param subjAltNameURI optional URI to embed in the subject alternative-name - * @return self-signed certificate - * @throws PGPException - * @throws NoSuchProviderException - * @throws InvalidKeyException - * @throws NoSuchAlgorithmException - * @throws SignatureException - * @throws CertificateException - * @author Bruno Harbulot - */ - public static X509Certificate createSelfSignedCert( - PGPSecretKey pgpSecKey, PGPPrivateKey pgpPrivKey, String subjAltNameURI) - throws PGPException, NoSuchProviderException, InvalidKeyException, NoSuchAlgorithmException, - SignatureException, CertificateException { - // get public key from secret key - PGPPublicKey pgpPubKey = pgpSecKey.getPublicKey(); - - // LOGGER.info("Key ID: " + Long.toHexString(pgpPubKey.getKeyID() & 0xffffffffL)); - - /* - * The X.509 Name to be the subject DN is prepared. The CN is extracted from the Secret Key - * user ID. - */ - Vector x509NameOids = new Vector(); - Vector x509NameValues = new Vector(); - - x509NameOids.add(X509Name.O); - x509NameValues.add(DN_COMMON_PART_O); - - x509NameOids.add(X509Name.OU); - x509NameValues.add(DN_COMMON_PART_OU); - - for (@SuppressWarnings("unchecked") - Iterator it = (Iterator) pgpSecKey.getUserIDs(); it.hasNext(); ) { - Object attrib = it.next(); - x509NameOids.add(X509Name.CN); - x509NameValues.add("CryptoCall"); - // x509NameValues.add(attrib.toString()); - } - - /* - * Currently unused. - */ - Log.d(Constants.TAG, "User attributes: "); - for (@SuppressWarnings("unchecked") - Iterator it = (Iterator) pgpSecKey.getUserAttributes(); it.hasNext(); ) { - Object attrib = it.next(); - Log.d(Constants.TAG, " - " + attrib + " -- " + attrib.getClass()); - } - - X509Name x509name = new X509Name(x509NameOids, x509NameValues); - - Log.d(Constants.TAG, "Subject DN: " + x509name); - - /* - * To check the signature from the certificate on the recipient side, the creation time - * needs to be embedded in the certificate. It seems natural to make this creation time be - * the "not-before" date of the X.509 certificate. Unlimited PGP keys have a validity of 0 - * second. In this case, the "not-after" date will be the same as the not-before date. This - * is something that needs to be checked by the service receiving this certificate. - */ - Date creationTime = pgpPubKey.getCreationTime(); - Log.d(Constants.TAG, - "pgp pub key creation time=" + DateFormat.getDateInstance().format(creationTime)); - Log.d(Constants.TAG, "pgp valid seconds=" + pgpPubKey.getValidSeconds()); - Date validTo = null; - if (pgpPubKey.getValidSeconds() > 0) { - validTo = new Date(creationTime.getTime() + 1000L * pgpPubKey.getValidSeconds()); - } - - X509Certificate selfSignedCert = createSelfSignedCert( - pgpPubKey.getKey(Constants.BOUNCY_CASTLE_PROVIDER_NAME), pgpPrivKey.getKey(), - x509name, creationTime, validTo, subjAltNameURI); - - return selfSignedCert; - } - - /** - * This is a password callback handler that will fill in a password automatically. Useful to - * configure passwords in advance, but should be used with caution depending on how much you - * allow passwords to be stored within your application. - * - * @author Bruno Harbulot. - */ - public static final class PredefinedPasswordCallbackHandler implements CallbackHandler { - - private char[] mPassword; - private String mPrompt; - - public PredefinedPasswordCallbackHandler(String password) { - this(password == null ? null : password.toCharArray(), null); - } - - public PredefinedPasswordCallbackHandler(char[] password) { - this(password, null); - } - - public PredefinedPasswordCallbackHandler(String password, String prompt) { - this(password == null ? null : password.toCharArray(), prompt); - } - - public PredefinedPasswordCallbackHandler(char[] password, String prompt) { - this.mPassword = password; - this.mPrompt = prompt; - } - - public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { - for (Callback callback : callbacks) { - if (callback instanceof PasswordCallback) { - PasswordCallback pwCallback = (PasswordCallback) callback; - if ((this.mPrompt == null) || (this.mPrompt.equals(pwCallback.getPrompt()))) { - pwCallback.setPassword(this.mPassword); - } - } else { - throw new UnsupportedCallbackException(callback, "Unrecognised callback."); - } - } - } - - protected final Object clone() throws CloneNotSupportedException { - throw new CloneNotSupportedException(); - } - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index 0999cc754..8f6b7a758 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -79,11 +79,6 @@ public class KeychainContract { String PACKAGE_NAME = "package_name"; // foreign key to api_apps.package_name } - public static final class KeyTypes { - public static final int PUBLIC = 0; - public static final int SECRET = 1; - } - public static final String CONTENT_AUTHORITY = Constants.PACKAGE_NAME + ".provider"; private static final Uri BASE_CONTENT_URI_INTERNAL = Uri @@ -285,15 +280,6 @@ public class KeychainContract { } - public static class DataStream { - public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() - .appendPath(BASE_DATA).build(); - - public static Uri buildDataStreamUri(String streamFilename) { - return CONTENT_URI.buildUpon().appendPath(streamFilename).build(); - } - } - private KeychainContract() { } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index c2e6adef5..b3165d347 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -155,8 +155,9 @@ public class KeychainDatabase extends SQLiteOpenHelper { } } // if it's us, do the import - if(iAmIt) + if (iAmIt) { checkAndImportApg(context); + } } @Override @@ -273,11 +274,11 @@ public class KeychainDatabase extends SQLiteOpenHelper { byte[] data = c.getBlob(0); PGPKeyRing ring = PgpConversionHelper.BytesToPGPKeyRing(data); ProviderHelper providerHelper = new ProviderHelper(context); - if(ring instanceof PGPPublicKeyRing) + if (ring instanceof PGPPublicKeyRing) { providerHelper.saveKeyRing((PGPPublicKeyRing) ring); - else if(ring instanceof PGPSecretKeyRing) + } else if(ring instanceof PGPSecretKeyRing) { providerHelper.saveKeyRing((PGPSecretKeyRing) ring); - else { + } else { Log.e(Constants.TAG, "Unknown blob data type!"); } } @@ -286,17 +287,17 @@ public class KeychainDatabase extends SQLiteOpenHelper { Log.e(Constants.TAG, "Error importing apg db!", e); return; } finally { - if(c != null) + if(c != null) { c.close(); - if(db != null) + } + if(db != null) { db.close(); + } } // TODO delete old db, if we are sure this works // context.deleteDatabase("apg.db"); Log.d(Constants.TAG, "All done, (not) deleting apg.db"); - } - } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 012948f63..1ad42b13a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -32,13 +32,12 @@ import android.text.TextUtils; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; +import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; -import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; -import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter; import org.sufficientlysecure.keychain.util.Log; import java.util.Arrays; @@ -67,8 +66,6 @@ public class KeychainProvider extends ContentProvider { private static final int KEY_RINGS_FIND_BY_EMAIL = 400; private static final int KEY_RINGS_FIND_BY_SUBKEY = 401; - // private static final int DATA_STREAM = 501; - protected UriMatcher mUriMatcher; /** @@ -166,15 +163,6 @@ public class KeychainProvider extends ContentProvider { matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/*/" + KeychainContract.PATH_ACCOUNTS + "/*", API_ACCOUNTS_BY_ACCOUNT_NAME); - /** - * data stream - * - *
-         * data / _
-         * 
- */ - // matcher.addURI(authority, KeychainContract.BASE_DATA + "/*", DATA_STREAM); - return matcher; } @@ -592,7 +580,6 @@ public class KeychainProvider extends ContentProvider { break; case KEY_RING_KEYS: - Log.d(Constants.TAG, "keys"); db.insertOrThrow(Tables.KEYS, null, values); keyId = values.getAsLong(Keys.MASTER_KEY_ID); break; @@ -708,7 +695,6 @@ public class KeychainProvider extends ContentProvider { final SQLiteDatabase db = mKeychainDatabase.getWritableDatabase(); - String defaultSelection = null; int count = 0; try { final int match = mUriMatcher.match(uri); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobContract.java deleted file mode 100644 index 3fdad0f59..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobContract.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2012-2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.provider; - -import android.net.Uri; -import android.provider.BaseColumns; -import org.sufficientlysecure.keychain.Constants; - -public class KeychainServiceBlobContract { - - interface BlobsColumns { - String KEY = "key"; - } - - public static final String CONTENT_AUTHORITY = Constants.PACKAGE_NAME + ".blobs"; - - private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY); - - public static class Blobs implements BlobsColumns, BaseColumns { - public static final Uri CONTENT_URI = BASE_CONTENT_URI; - } - - private KeychainServiceBlobContract() { - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobDatabase.java deleted file mode 100644 index 97f76f44e..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobDatabase.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2012-2014 Dominik Schürmann - * Copyright (C) 2011 Markus Doits - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.provider; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.provider.BaseColumns; -import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.BlobsColumns; - -public class KeychainServiceBlobDatabase extends SQLiteOpenHelper { - private static final String DATABASE_NAME = "openkeychain_blob.db"; - private static final int DATABASE_VERSION = 2; - - public static final String TABLE = "data"; - - public KeychainServiceBlobDatabase(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + TABLE + " ( " + BaseColumns._ID - + " INTEGER PRIMARY KEY AUTOINCREMENT, " + BlobsColumns.KEY + " TEXT NOT NULL)"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - // no upgrade necessary yet - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobProvider.java deleted file mode 100644 index aa30e845d..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobProvider.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2012-2013 Dominik Schürmann - * Copyright (C) 2011 Markus Doits - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.provider; - -import android.content.ContentProvider; -import android.content.ContentUris; -import android.content.ContentValues; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.net.Uri; -import android.os.ParcelFileDescriptor; -import android.provider.BaseColumns; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.Blobs; -import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.BlobsColumns; -import org.sufficientlysecure.keychain.util.Log; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.List; -import java.util.UUID; - -public class KeychainServiceBlobProvider extends ContentProvider { - private static final String STORE_PATH = Constants.Path.APP_DIR + "/KeychainBlobs"; - - private KeychainServiceBlobDatabase mBlobDatabase = null; - - public KeychainServiceBlobProvider() { - File dir = new File(STORE_PATH); - dir.mkdirs(); - } - - @Override - public boolean onCreate() { - mBlobDatabase = new KeychainServiceBlobDatabase(getContext()); - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public Uri insert(Uri uri, ContentValues ignored) { - // ContentValues are actually ignored, because we want to store a blob with no more - // information but have to create an record with the password generated here first - ContentValues vals = new ContentValues(); - - // Insert a random key in the database. This has to provided by the caller when updating or - // getting the blob - String password = UUID.randomUUID().toString(); - vals.put(BlobsColumns.KEY, password); - - SQLiteDatabase db = mBlobDatabase.getWritableDatabase(); - long newRowId = db.insert(KeychainServiceBlobDatabase.TABLE, null, vals); - Uri insertedUri = ContentUris.withAppendedId(Blobs.CONTENT_URI, newRowId); - - return Uri.withAppendedPath(insertedUri, password); - } - - /** - * {@inheritDoc} - */ - @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) throws SecurityException, - FileNotFoundException { - Log.d(Constants.TAG, "openFile() called with uri: " + uri.toString() + " and mode: " + mode); - - List segments = uri.getPathSegments(); - if (segments.size() < 2) { - throw new SecurityException("Password not found in URI"); - } - String id = segments.get(0); - String key = segments.get(1); - - Log.d(Constants.TAG, "Got id: " + id + " and key: " + key); - - // get the data - SQLiteDatabase db = mBlobDatabase.getReadableDatabase(); - Cursor result = db.query(KeychainServiceBlobDatabase.TABLE, new String[]{BaseColumns._ID}, - BaseColumns._ID + " = ? and " + BlobsColumns.KEY + " = ?", - new String[]{id, key}, null, null, null); - - if (result.getCount() == 0) { - // either the key is wrong or no id exists - throw new FileNotFoundException("No file found with that ID and/or password"); - } - - File targetFile = new File(STORE_PATH, id); - if (mode.equals("w")) { - Log.d(Constants.TAG, "Try to open file w"); - if (!targetFile.exists()) { - try { - targetFile.createNewFile(); - } catch (IOException e) { - Log.e(Constants.TAG, "Got IEOException on creating new file", e); - throw new FileNotFoundException("Could not create file to write to"); - } - } - return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_WRITE_ONLY - | ParcelFileDescriptor.MODE_TRUNCATE); - } else if (mode.equals("r")) { - Log.d(Constants.TAG, "Try to open file r"); - if (!targetFile.exists()) { - throw new FileNotFoundException("Error: Could not find the file requested"); - } - return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_READ_ONLY); - } - - return null; - } - - /** - * {@inheritDoc} - */ - @Override - public String getType(Uri uri) { - return null; - } - - /** - * {@inheritDoc} - */ - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - return null; - } - - /** - * {@inheritDoc} - */ - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - return 0; - } - - /** - * {@inheritDoc} - */ - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - return 0; - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 977c92233..049a47159 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -36,8 +36,8 @@ import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity; import org.sufficientlysecure.keychain.service.PassphraseCacheService; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java index 82d41dff7..f70324e2c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java @@ -44,6 +44,15 @@ import java.util.Arrays; * Abstract service class for remote APIs that handle app registration and user input. */ public abstract class RemoteService extends Service { + + public static class WrongPackageSignatureException extends Exception { + private static final long serialVersionUID = -8294642703122196028L; + + public WrongPackageSignatureException(String message) { + super(message); + } + } + Context mContext; ProviderHelper mProviderHelper; @@ -51,6 +60,12 @@ public abstract class RemoteService extends Service { return mContext; } + /** + * Checks if caller is allowed to access the API + * + * @param data + * @return null if caller is allowed, or a Bundle with a PendingIntent + */ protected Intent isAllowed(Intent data) { try { if (isCallerAllowed(false)) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/WrongPackageSignatureException.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/WrongPackageSignatureException.java deleted file mode 100644 index 9084796cb..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/WrongPackageSignatureException.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2013-2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.remote; - -public class WrongPackageSignatureException extends Exception { - - private static final long serialVersionUID = -8294642703122196028L; - - public WrongPackageSignatureException(String message) { - super(message); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/PausableThreadPoolExecutor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/PausableThreadPoolExecutor.java deleted file mode 100644 index f9b80f229..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/PausableThreadPoolExecutor.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2013-2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.util; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.RejectedExecutionHandler; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Example from - * http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html - */ -public class PausableThreadPoolExecutor extends ThreadPoolExecutor { - - public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, - TimeUnit unit, BlockingQueue workQueue, - RejectedExecutionHandler handler) { - super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); - } - - public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, - TimeUnit unit, BlockingQueue workQueue, - ThreadFactory threadFactory, - RejectedExecutionHandler handler) { - super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); - } - - public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, - TimeUnit unit, BlockingQueue workQueue, - ThreadFactory threadFactory) { - super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); - } - - public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, - TimeUnit unit, BlockingQueue workQueue) { - super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); - } - - private boolean mIsPaused; - private ReentrantLock mPauseLock = new ReentrantLock(); - private Condition mUnPaused = mPauseLock.newCondition(); - - protected void beforeExecute(Thread t, Runnable r) { - super.beforeExecute(t, r); - mPauseLock.lock(); - try { - while (mIsPaused) { - mUnPaused.await(); - } - } catch (InterruptedException ie) { - t.interrupt(); - } finally { - mPauseLock.unlock(); - } - } - - public void pause() { - mPauseLock.lock(); - try { - mIsPaused = true; - } finally { - mPauseLock.unlock(); - } - } - - public void resume() { - mPauseLock.lock(); - try { - mIsPaused = false; - mUnPaused.signalAll(); - } finally { - mPauseLock.unlock(); - } - } -} diff --git a/Resources/old extended service/src/main/java/PgpToX509.java b/Resources/old extended service/src/main/java/PgpToX509.java new file mode 100644 index 000000000..d83575bad --- /dev/null +++ b/Resources/old extended service/src/main/java/PgpToX509.java @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2012-2014 Dominik Schürmann + * Copyright (C) 2010-2014 Thialfihar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.x509.AuthorityKeyIdentifier; +import org.spongycastle.asn1.x509.BasicConstraints; +import org.spongycastle.asn1.x509.GeneralName; +import org.spongycastle.asn1.x509.GeneralNames; +import org.spongycastle.asn1.x509.SubjectKeyIdentifier; +import org.spongycastle.asn1.x509.X509Extensions; +import org.spongycastle.asn1.x509.X509Name; +import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPPrivateKey; +import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPSecretKey; +import org.spongycastle.x509.X509V3CertificateGenerator; +import org.spongycastle.x509.extension.AuthorityKeyIdentifierStructure; +import org.spongycastle.x509.extension.SubjectKeyIdentifierStructure; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.Log; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SignatureException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.text.DateFormat; +import java.util.Date; +import java.util.Iterator; +import java.util.Vector; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; + +public class PgpToX509 { + public static final String DN_COMMON_PART_O = "OpenPGP to X.509 Bridge"; + public static final String DN_COMMON_PART_OU = "OpenPGP Keychain cert"; + + /** + * Creates a self-signed certificate from a public and private key. The (critical) key-usage + * extension is set up with: digital signature, non-repudiation, key-encipherment, key-agreement + * and certificate-signing. The (non-critical) Netscape extension is set up with: SSL client and + * S/MIME. A URI subjectAltName may also be set up. + * + * @param pubKey public key + * @param privKey private key + * @param subject subject (and issuer) DN for this certificate, RFC 2253 format preferred. + * @param startDate date from which the certificate will be valid (defaults to current date and time + * if null) + * @param endDate date until which the certificate will be valid (defaults to current date and time + * if null) * + * @param subjAltNameURI URI to be placed in subjectAltName + * @return self-signed certificate + * @throws InvalidKeyException + * @throws SignatureException + * @throws NoSuchAlgorithmException + * @throws IllegalStateException + * @throws NoSuchProviderException + * @throws CertificateException + * @throws Exception + * @author Bruno Harbulot + */ + public static X509Certificate createSelfSignedCert( + PublicKey pubKey, PrivateKey privKey, X509Name subject, Date startDate, Date endDate, + String subjAltNameURI) + throws InvalidKeyException, IllegalStateException, NoSuchAlgorithmException, + SignatureException, CertificateException, NoSuchProviderException { + + X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator(); + + certGenerator.reset(); + /* + * Sets up the subject distinguished name. Since it's a self-signed certificate, issuer and + * subject are the same. + */ + certGenerator.setIssuerDN(subject); + certGenerator.setSubjectDN(subject); + + /* + * Sets up the validity dates. + */ + if (startDate == null) { + startDate = new Date(System.currentTimeMillis()); + } + certGenerator.setNotBefore(startDate); + if (endDate == null) { + endDate = new Date(startDate.getTime() + (365L * 24L * 60L * 60L * 1000L)); + Log.d(Constants.TAG, "end date is=" + DateFormat.getDateInstance().format(endDate)); + } + + certGenerator.setNotAfter(endDate); + + /* + * The serial-number of this certificate is 1. It makes sense because it's self-signed. + */ + certGenerator.setSerialNumber(BigInteger.ONE); + /* + * Sets the public-key to embed in this certificate. + */ + certGenerator.setPublicKey(pubKey); + /* + * Sets the signature algorithm. + */ + String pubKeyAlgorithm = pubKey.getAlgorithm(); + if (pubKeyAlgorithm.equals("DSA")) { + certGenerator.setSignatureAlgorithm("SHA1WithDSA"); + } else if (pubKeyAlgorithm.equals("RSA")) { + certGenerator.setSignatureAlgorithm("SHA1WithRSAEncryption"); + } else { + RuntimeException re = new RuntimeException("Algorithm not recognised: " + + pubKeyAlgorithm); + Log.e(Constants.TAG, re.getMessage(), re); + throw re; + } + + /* + * Adds the Basic Constraint (CA: true) extension. + */ + certGenerator.addExtension(X509Extensions.BasicConstraints, true, + new BasicConstraints(true)); + + /* + * Adds the subject key identifier extension. + */ + SubjectKeyIdentifier subjectKeyIdentifier = new SubjectKeyIdentifierStructure(pubKey); + certGenerator + .addExtension(X509Extensions.SubjectKeyIdentifier, false, subjectKeyIdentifier); + + /* + * Adds the authority key identifier extension. + */ + AuthorityKeyIdentifier authorityKeyIdentifier = new AuthorityKeyIdentifierStructure(pubKey); + certGenerator.addExtension(X509Extensions.AuthorityKeyIdentifier, false, + authorityKeyIdentifier); + + /* + * Adds the subject alternative-name extension. + */ + if (subjAltNameURI != null) { + GeneralNames subjectAltNames = new GeneralNames(new GeneralName( + GeneralName.uniformResourceIdentifier, subjAltNameURI)); + certGenerator.addExtension(X509Extensions.SubjectAlternativeName, false, + subjectAltNames); + } + + /* + * Creates and sign this certificate with the private key corresponding to the public key of + * the certificate (hence the name "self-signed certificate"). + */ + X509Certificate cert = certGenerator.generate(privKey); + + /* + * Checks that this certificate has indeed been correctly signed. + */ + cert.verify(pubKey); + + return cert; + } + + /** + * Creates a self-signed certificate from a PGP Secret Key. + * + * @param pgpSecKey PGP Secret Key (from which one can extract the public and private + * keys and other attributes). + * @param pgpPrivKey PGP Private Key corresponding to the Secret Key (password callbacks + * should be done before calling this method) + * @param subjAltNameURI optional URI to embed in the subject alternative-name + * @return self-signed certificate + * @throws PGPException + * @throws NoSuchProviderException + * @throws InvalidKeyException + * @throws NoSuchAlgorithmException + * @throws SignatureException + * @throws CertificateException + * @author Bruno Harbulot + */ + public static X509Certificate createSelfSignedCert( + PGPSecretKey pgpSecKey, PGPPrivateKey pgpPrivKey, String subjAltNameURI) + throws PGPException, NoSuchProviderException, InvalidKeyException, NoSuchAlgorithmException, + SignatureException, CertificateException { + // get public key from secret key + PGPPublicKey pgpPubKey = pgpSecKey.getPublicKey(); + + // LOGGER.info("Key ID: " + Long.toHexString(pgpPubKey.getKeyID() & 0xffffffffL)); + + /* + * The X.509 Name to be the subject DN is prepared. The CN is extracted from the Secret Key + * user ID. + */ + Vector x509NameOids = new Vector(); + Vector x509NameValues = new Vector(); + + x509NameOids.add(X509Name.O); + x509NameValues.add(DN_COMMON_PART_O); + + x509NameOids.add(X509Name.OU); + x509NameValues.add(DN_COMMON_PART_OU); + + for (@SuppressWarnings("unchecked") + Iterator it = (Iterator) pgpSecKey.getUserIDs(); it.hasNext(); ) { + Object attrib = it.next(); + x509NameOids.add(X509Name.CN); + x509NameValues.add("CryptoCall"); + // x509NameValues.add(attrib.toString()); + } + + /* + * Currently unused. + */ + Log.d(Constants.TAG, "User attributes: "); + for (@SuppressWarnings("unchecked") + Iterator it = (Iterator) pgpSecKey.getUserAttributes(); it.hasNext(); ) { + Object attrib = it.next(); + Log.d(Constants.TAG, " - " + attrib + " -- " + attrib.getClass()); + } + + X509Name x509name = new X509Name(x509NameOids, x509NameValues); + + Log.d(Constants.TAG, "Subject DN: " + x509name); + + /* + * To check the signature from the certificate on the recipient side, the creation time + * needs to be embedded in the certificate. It seems natural to make this creation time be + * the "not-before" date of the X.509 certificate. Unlimited PGP keys have a validity of 0 + * second. In this case, the "not-after" date will be the same as the not-before date. This + * is something that needs to be checked by the service receiving this certificate. + */ + Date creationTime = pgpPubKey.getCreationTime(); + Log.d(Constants.TAG, + "pgp pub key creation time=" + DateFormat.getDateInstance().format(creationTime)); + Log.d(Constants.TAG, "pgp valid seconds=" + pgpPubKey.getValidSeconds()); + Date validTo = null; + if (pgpPubKey.getValidSeconds() > 0) { + validTo = new Date(creationTime.getTime() + 1000L * pgpPubKey.getValidSeconds()); + } + + X509Certificate selfSignedCert = createSelfSignedCert( + pgpPubKey.getKey(Constants.BOUNCY_CASTLE_PROVIDER_NAME), pgpPrivKey.getKey(), + x509name, creationTime, validTo, subjAltNameURI); + + return selfSignedCert; + } + + /** + * This is a password callback handler that will fill in a password automatically. Useful to + * configure passwords in advance, but should be used with caution depending on how much you + * allow passwords to be stored within your application. + * + * @author Bruno Harbulot. + */ + public static final class PredefinedPasswordCallbackHandler implements CallbackHandler { + + private char[] mPassword; + private String mPrompt; + + public PredefinedPasswordCallbackHandler(String password) { + this(password == null ? null : password.toCharArray(), null); + } + + public PredefinedPasswordCallbackHandler(char[] password) { + this(password, null); + } + + public PredefinedPasswordCallbackHandler(String password, String prompt) { + this(password == null ? null : password.toCharArray(), prompt); + } + + public PredefinedPasswordCallbackHandler(char[] password, String prompt) { + this.mPassword = password; + this.mPrompt = prompt; + } + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (Callback callback : callbacks) { + if (callback instanceof PasswordCallback) { + PasswordCallback pwCallback = (PasswordCallback) callback; + if ((this.mPrompt == null) || (this.mPrompt.equals(pwCallback.getPrompt()))) { + pwCallback.setPassword(this.mPassword); + } + } else { + throw new UnsupportedCallbackException(callback, "Unrecognised callback."); + } + } + } + + protected final Object clone() throws CloneNotSupportedException { + throw new CloneNotSupportedException(); + } + } +} -- cgit v1.2.3