From 0fd5b45df913d1524aa400a644c48dc91044d9bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sun, 10 Jan 2016 17:17:57 +0100 Subject: Use more generic 'Security Token' where possible, add sutitle to create key what tokens are supported --- .../keychain/ui/ViewKeySecurityTokenFragment.java | 222 +++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeySecurityTokenFragment.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeySecurityTokenFragment.java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeySecurityTokenFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeySecurityTokenFragment.java new file mode 100644 index 000000000..48e41c7bb --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeySecurityTokenFragment.java @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * Copyright (C) 2015 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.ui; + + +import java.nio.ByteBuffer; +import java.util.Arrays; + +import android.database.Cursor; +import android.os.Bundle; +import android.support.v4.app.LoaderManager.LoaderCallbacks; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import org.spongycastle.util.encoders.Hex; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult; +import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; +import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; +import org.sufficientlysecure.keychain.service.PromoteKeyringParcel; +import org.sufficientlysecure.keychain.ui.base.QueueingCryptoOperationFragment; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; + + +public class ViewKeySecurityTokenFragment + extends QueueingCryptoOperationFragment + implements LoaderCallbacks { + + public static final String ARG_MASTER_KEY_ID = "master_key_id"; + public static final String ARG_FINGERPRINT = "fingerprint"; + public static final String ARG_USER_ID = "user_id"; + public static final String ARG_CARD_AID = "aid"; + + private byte[][] mFingerprints; + private String mUserId; + private byte[] mCardAid; + private long mMasterKeyId; + private long[] mSubKeyIds; + + private Button vButton; + private TextView vStatus; + + public static ViewKeySecurityTokenFragment newInstance(long masterKeyId, + byte[] fingerprints, String userId, byte[] aid) { + ViewKeySecurityTokenFragment frag = new ViewKeySecurityTokenFragment(); + + Bundle args = new Bundle(); + args.putLong(ARG_MASTER_KEY_ID, masterKeyId); + args.putByteArray(ARG_FINGERPRINT, fingerprints); + args.putString(ARG_USER_ID, userId); + args.putByteArray(ARG_CARD_AID, aid); + frag.setArguments(args); + + return frag; + } + + public ViewKeySecurityTokenFragment() { + super(null); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Bundle args = getArguments(); + ByteBuffer buf = ByteBuffer.wrap(args.getByteArray(ARG_FINGERPRINT)); + mFingerprints = new byte[buf.remaining()/20][]; + for (int i = 0; i < mFingerprints.length; i++) { + mFingerprints[i] = new byte[20]; + buf.get(mFingerprints[i]); + } + mUserId = args.getString(ARG_USER_ID); + mCardAid = args.getByteArray(ARG_CARD_AID); + + mMasterKeyId = args.getLong(ARG_MASTER_KEY_ID); + + getLoaderManager().initLoader(0, null, this); + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.view_key_security_token, null); + + TextView vSerNo = (TextView) view.findViewById(R.id.token_serno); + TextView vUserId = (TextView) view.findViewById(R.id.token_userid); + + String serno = Hex.toHexString(mCardAid, 10, 4); + vSerNo.setText(getString(R.string.security_token_serial_no, serno)); + + if (!mUserId.isEmpty()) { + vUserId.setText(getString(R.string.security_token_key_holder, mUserId)); + } else { + vUserId.setText(getString(R.string.security_token_key_holder_not_set)); + } + + vButton = (Button) view.findViewById(R.id.button_bind); + vButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + promoteToSecretKey(); + } + }); + + vStatus = (TextView) view.findViewById(R.id.token_status); + + return view; + } + + public void promoteToSecretKey() { + long[] subKeyIds = new long[mFingerprints.length]; + for (int i = 0; i < subKeyIds.length; i++) { + subKeyIds[i] = KeyFormattingUtils.getKeyIdFromFingerprint(mFingerprints[i]); + } + + // mMasterKeyId and mCardAid are already set + mSubKeyIds = subKeyIds; + + cryptoOperation(); + } + + public static final String[] PROJECTION = new String[]{ + Keys._ID, + Keys.KEY_ID, + Keys.RANK, + Keys.HAS_SECRET, + Keys.FINGERPRINT + }; + // private static final int INDEX_KEY_ID = 1; + // private static final int INDEX_RANK = 2; + private static final int INDEX_HAS_SECRET = 3; + private static final int INDEX_FINGERPRINT = 4; + + @Override + public Loader onCreateLoader(int id, Bundle args) { + return new CursorLoader(getActivity(), Keys.buildKeysUri(mMasterKeyId), + PROJECTION, null, null, null); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + if (!data.moveToFirst()) { + // wut? + return; + } + + boolean allBound = true; + boolean noneBound = true; + + do { + SecretKeyType keyType = SecretKeyType.fromNum(data.getInt(INDEX_HAS_SECRET)); + byte[] fingerprint = data.getBlob(INDEX_FINGERPRINT); + Integer index = naiveIndexOf(mFingerprints, fingerprint); + if (index == null) { + continue; + } + if (keyType == SecretKeyType.DIVERT_TO_CARD) { + noneBound = false; + } else { + allBound = false; + } + } while (data.moveToNext()); + + if (allBound) { + vButton.setVisibility(View.GONE); + vStatus.setText(R.string.security_token_status_bound); + } else { + vButton.setVisibility(View.VISIBLE); + vStatus.setText(noneBound + ? R.string.security_token_status_unbound + : R.string.security_token_status_partly); + } + + } + + static private Integer naiveIndexOf(byte[][] haystack, byte[] needle) { + for (int i = 0; i < haystack.length; i++) { + if (Arrays.equals(needle, haystack[i])) { + return i; + } + } + return null; + } + + @Override + public void onLoaderReset(Loader loader) { + + } + + @Override + public PromoteKeyringParcel createOperationInput() { + return new PromoteKeyringParcel(mMasterKeyId, mCardAid, mSubKeyIds); + } + + @Override + public void onQueuedOperationSuccess(PromoteKeyResult result) { + result.createNotify(getActivity()).show(); + } + +} -- cgit v1.2.3