diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TrustIdentityDataAccessObject.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TrustIdentityDataAccessObject.java new file mode 100644 index 000000000..9eaba736f --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TrustIdentityDataAccessObject.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2012-2014 Dominik Schürmann + * Copyright (C) 2014-2016 Vincent Breitmoser + * + * 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.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; + +import org.sufficientlysecure.keychain.provider.KeychainContract.ApiTrustIdentity; + + +public class TrustIdentityDataAccessObject { + private final SimpleContentResolverInterface mQueryInterface; + private final String packageName; + + + public TrustIdentityDataAccessObject(Context context, String packageName) { + this.packageName = packageName; + + final ContentResolver contentResolver = context.getContentResolver(); + mQueryInterface = new SimpleContentResolverInterface() { + @Override + public Cursor query(Uri contentUri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + return contentResolver.query(contentUri, projection, selection, selectionArgs, sortOrder); + } + + @Override + public Uri insert(Uri contentUri, ContentValues values) { + return contentResolver.insert(contentUri, values); + } + + @Override + public int update(Uri contentUri, ContentValues values, String where, String[] selectionArgs) { + return contentResolver.update(contentUri, values, where, selectionArgs); + } + + @Override + public int delete(Uri contentUri, String where, String[] selectionArgs) { + return contentResolver.delete(contentUri, where, selectionArgs); + } + }; + } + + public TrustIdentityDataAccessObject(SimpleContentResolverInterface queryInterface, String packageName) { + mQueryInterface = queryInterface; + this.packageName = packageName; + } + + public Long getMasterKeyIdForTrustId(String trustId) { + Cursor cursor = mQueryInterface.query( + ApiTrustIdentity.buildByPackageNameAndTrustId(packageName, trustId), null, null, null, null); + + try { + if (cursor != null && cursor.moveToFirst()) { + int masterKeyIdColumn = cursor.getColumnIndex(ApiTrustIdentity.MASTER_KEY_ID); + return cursor.getLong(masterKeyIdColumn); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + + return null; + } +} 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 bec9ef501..c514bc3f6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -46,6 +46,7 @@ import org.openintents.openpgp.OpenPgpDecryptionResult; import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpSignatureResult; +import org.openintents.openpgp.OpenPgpSignatureResult.TrustIdentityResult; import org.openintents.openpgp.util.OpenPgpApi; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.operations.BackupOperation; @@ -68,6 +69,7 @@ import org.sufficientlysecure.keychain.provider.KeyRepository; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.OverriddenWarningsRepository; +import org.sufficientlysecure.keychain.provider.TrustIdentityDataAccessObject; import org.sufficientlysecure.keychain.remote.OpenPgpServiceKeyIdExtractor.KeyIdResult; import org.sufficientlysecure.keychain.remote.OpenPgpServiceKeyIdExtractor.KeyIdResultStatus; import org.sufficientlysecure.keychain.service.BackupKeyringParcel; @@ -82,23 +84,26 @@ public class OpenPgpService extends Service { public static final int API_VERSION_WITHOUT_SIGNATURE_ONLY_FLAG = 8; public static final int API_VERSION_WITH_DECRYPTION_RESULT = 8; public static final int API_VERSION_WITH_RESULT_NO_SIGNATURE = 8; + public static final int API_VERSION_WITH_TRUST_IDENTITIES = 12; public static final List SUPPORTED_VERSIONS = - Collections.unmodifiableList(Arrays.asList(7, 8, 9, 10, 11)); + Collections.unmodifiableList(Arrays.asList(7, 8, 9, 10, 11, 12)); private ApiPermissionHelper mApiPermissionHelper; private KeyRepository mKeyRepository; private ApiDataAccessObject mApiDao; private OpenPgpServiceKeyIdExtractor mKeyIdExtractor; private ApiPendingIntentFactory mApiPendingIntentFactory; + private TrustIdentityDataAccessObject mTrustIdentityDao; @Override public void onCreate() { super.onCreate(); - mApiPermissionHelper = new ApiPermissionHelper(this, new ApiDataAccessObject(this)); mKeyRepository = KeyRepository.createDatabaseInteractor(this); mApiDao = new ApiDataAccessObject(this); - + mApiPermissionHelper = new ApiPermissionHelper(this, mApiDao); + mTrustIdentityDao = new TrustIdentityDataAccessObject(getBaseContext(), + mApiPermissionHelper.getCurrentCallingPackage()); mApiPendingIntentFactory = new ApiPendingIntentFactory(getBaseContext()); mKeyIdExtractor = OpenPgpServiceKeyIdExtractor.getInstance(getContentResolver(), mApiPendingIntentFactory); } @@ -528,9 +533,38 @@ public class OpenPgpService extends Service { } } + String trustIdentity = data.getStringExtra(OpenPgpApi.EXTRA_TRUST_IDENTITY); + if (trustIdentity != null) { + if (targetApiVersion < API_VERSION_WITH_TRUST_IDENTITIES) { + throw new IllegalStateException("API version conflict, trust identities are supported v12 and up!"); + } + signatureResult = addTrustIdentityInfoToSignatureResult(signatureResult, trustIdentity); + } + result.putExtra(OpenPgpApi.RESULT_SIGNATURE, signatureResult); } + private OpenPgpSignatureResult addTrustIdentityInfoToSignatureResult(OpenPgpSignatureResult signatureResult, + String trustIdentity) { + boolean hasValidSignature = + signatureResult.getResult() == OpenPgpSignatureResult.RESULT_VALID_KEY_CONFIRMED || + signatureResult.getResult() == OpenPgpSignatureResult.RESULT_VALID_KEY_UNCONFIRMED; + if (!hasValidSignature) { + return signatureResult; + } + + Long tofuTrustedMasterKeyId = mTrustIdentityDao.getMasterKeyIdForTrustId(trustIdentity); + + long masterKeyId = signatureResult.getKeyId(); + if (tofuTrustedMasterKeyId == null) { + return signatureResult.withTrustIdentityResult(TrustIdentityResult.NEW); + } else if (masterKeyId == tofuTrustedMasterKeyId) { + return signatureResult.withTrustIdentityResult(TrustIdentityResult.OK); + } else { + return signatureResult.withTrustIdentityResult(TrustIdentityResult.MISMATCH); + } + } + private Intent getKeyImpl(Intent data, OutputStream outputStream) { try { long masterKeyId = data.getLongExtra(OpenPgpApi.EXTRA_KEY_ID, 0); diff --git a/extern/openpgp-api-lib b/extern/openpgp-api-lib index 182852fce..fde49c854 160000 --- a/extern/openpgp-api-lib +++ b/extern/openpgp-api-lib @@ -1 +1 @@ -Subproject commit 182852fcec5d62024e8e5fb2c84272cae63a8ba0 +Subproject commit fde49c854fd7aa217169061b35b97c9231119c18