yubikey certifications!

This commit is contained in:
Vincent Breitmoser
2015-03-18 21:12:31 +01:00
parent aca54e31ea
commit d46fc3740b
15 changed files with 476 additions and 241 deletions

View File

@@ -30,6 +30,8 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
import org.sufficientlysecure.keychain.pgp.PgpCertifyOperation;
import org.sufficientlysecure.keychain.pgp.PgpCertifyOperation.PgpCertifyResult;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
@@ -38,6 +40,8 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException
import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
import org.sufficientlysecure.keychain.service.input.NfcOperationsParcel;
import org.sufficientlysecure.keychain.service.input.NfcOperationsParcel.NfcSignOperationsBuilder;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
@@ -73,10 +77,6 @@ public class CertifyOperation extends BaseOperation {
mProviderHelper.getCanonicalizedSecretKeyRing(parcel.mMasterKeyId);
log.add(LogType.MSG_CRT_UNLOCK, 1);
certificationKey = secretKeyRing.getSecretKey();
if (certificationKey.getSecretKeyType() == SecretKeyType.DIVERT_TO_CARD) {
log.add(LogType.MSG_CRT_ERROR_DIVERT, 2);
return new CertifyResult(CertifyResult.RESULT_ERROR, log);
}
// certification is always with the master key id, so use that one
String passphrase = getCachedPassphrase(parcel.mMasterKeyId, parcel.mMasterKeyId);
@@ -102,6 +102,8 @@ public class CertifyOperation extends BaseOperation {
int certifyOk = 0, certifyError = 0, uploadOk = 0, uploadError = 0;
NfcSignOperationsBuilder allRequiredInput = new NfcSignOperationsBuilder(parcel.getSignatureTime());
// Work through all requested certifications
for (CertifyAction action : parcel.mCertifyActions) {
@@ -122,28 +124,21 @@ public class CertifyOperation extends BaseOperation {
CanonicalizedPublicKeyRing publicRing =
mProviderHelper.getCanonicalizedPublicKeyRing(action.mMasterKeyId);
UncachedKeyRing certifiedKey = null;
if (action.mUserIds != null) {
log.add(LogType.MSG_CRT_CERTIFY_UIDS, 2, action.mUserIds.size(),
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
PgpCertifyOperation op = new PgpCertifyOperation();
PgpCertifyResult result = op.certify(certificationKey, publicRing,
log, 2, action, parcel.getSignatureData(), parcel.getSignatureTime());
certifiedKey = certificationKey.certifyUserIds(
publicRing, action.mUserIds, null, null);
}
if (action.mUserAttributes != null) {
log.add(LogType.MSG_CRT_CERTIFY_UATS, 2, action.mUserAttributes.size(),
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
certifiedKey = certificationKey.certifyUserAttributes(
publicRing, action.mUserAttributes, null, null);
}
if (certifiedKey == null) {
if (!result.success()) {
certifyError += 1;
log.add(LogType.MSG_CRT_WARN_CERT_FAILED, 3);
continue;
}
certifiedKeys.add(certifiedKey);
if (result.nfcInputRequired()) {
NfcOperationsParcel requiredInput = result.getRequiredInput();
allRequiredInput.addAll(requiredInput);
continue;
}
certifiedKeys.add(result.getCertifiedRing());
} catch (NotFoundException e) {
certifyError += 1;
@@ -152,6 +147,11 @@ public class CertifyOperation extends BaseOperation {
}
if ( ! allRequiredInput.isEmpty()) {
log.add(LogType.MSG_CRT_NFC_RETURN, 1);
return new CertifyResult(log, allRequiredInput.build());
}
log.add(LogType.MSG_CRT_SAVING, 1);
// Check if we were cancelled

View File

@@ -23,6 +23,7 @@ import android.content.Intent;
import android.os.Parcel;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.service.input.NfcOperationsParcel;
import org.sufficientlysecure.keychain.ui.LogDisplayActivity;
import org.sufficientlysecure.keychain.ui.LogDisplayFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
@@ -30,16 +31,19 @@ import org.sufficientlysecure.keychain.ui.util.Notify.ActionListener;
import org.sufficientlysecure.keychain.ui.util.Notify.Showable;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
public class CertifyResult extends OperationResult {
public class CertifyResult extends InputPendingResult {
int mCertifyOk, mCertifyError, mUploadOk, mUploadError;
public CertifyResult(int result, OperationLog log) {
super(result, log);
}
public CertifyResult(OperationLog log, NfcOperationsParcel requiredInput) {
super(log, requiredInput);
}
public CertifyResult(int result, OperationLog log, int certifyOk, int certifyError, int uploadOk, int uploadError) {
this(result, log);
super(result, log);
mCertifyOk = certifyOk;
mCertifyError = certifyError;
mUploadOk = uploadOk;

View File

@@ -0,0 +1,76 @@
package org.sufficientlysecure.keychain.operations.results;
import android.os.Parcel;
import org.sufficientlysecure.keychain.service.input.NfcOperationsParcel;
public class InputPendingResult extends OperationResult {
// the fourth bit indicates a "data pending" result! (it's also a form of non-success)
public static final int RESULT_PENDING = RESULT_ERROR + 8;
public static final int RESULT_PENDING_PASSPHRASE = RESULT_PENDING + 16;
public static final int RESULT_PENDING_NFC = RESULT_PENDING + 32;
final NfcOperationsParcel mRequiredInput;
final Long mKeyIdPassphraseNeeded;
public InputPendingResult(int result, OperationLog log) {
super(result, log);
mRequiredInput = null;
mKeyIdPassphraseNeeded = null;
}
public InputPendingResult(OperationLog log, NfcOperationsParcel requiredInput) {
super(RESULT_PENDING_NFC, log);
mRequiredInput = requiredInput;
mKeyIdPassphraseNeeded = null;
}
public InputPendingResult(OperationLog log, long keyIdPassphraseNeeded) {
super(RESULT_PENDING_PASSPHRASE, log);
mRequiredInput = null;
mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
}
public InputPendingResult(Parcel source) {
super(source);
mRequiredInput = source.readParcelable(getClass().getClassLoader());
mKeyIdPassphraseNeeded = source.readInt() != 0 ? source.readLong() : null;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeParcelable(mRequiredInput, 0);
if (mKeyIdPassphraseNeeded != null) {
dest.writeInt(1);
dest.writeLong(mKeyIdPassphraseNeeded);
} else {
dest.writeInt(0);
}
}
public boolean isPending() {
return (mResult & RESULT_PENDING) == RESULT_PENDING;
}
public boolean isNfcPending() {
return (mResult & RESULT_PENDING_NFC) == RESULT_PENDING_NFC;
}
public boolean isPassphrasePending() {
return (mResult & RESULT_PENDING_PASSPHRASE) == RESULT_PENDING_PASSPHRASE;
}
public NfcOperationsParcel getNfcOperationsParcel() {
return mRequiredInput;
}
public long getPassphraseKeyId() {
return mKeyIdPassphraseNeeded;
}
}

View File

@@ -697,9 +697,9 @@ public abstract class OperationResult implements Parcelable {
MSG_CRT_ERROR_MASTER_NOT_FOUND (LogLevel.ERROR, R.string.msg_crt_error_master_not_found),
MSG_CRT_ERROR_NOTHING (LogLevel.ERROR, R.string.msg_crt_error_nothing),
MSG_CRT_ERROR_UNLOCK (LogLevel.ERROR, R.string.msg_crt_error_unlock),
MSG_CRT_ERROR_DIVERT (LogLevel.ERROR, R.string.msg_crt_error_divert),
MSG_CRT (LogLevel.START, R.string.msg_crt),
MSG_CRT_MASTER_FETCH (LogLevel.DEBUG, R.string.msg_crt_master_fetch),
MSG_CRT_NFC_RETURN (LogLevel.OK, R.string.msg_crt_nfc_return),
MSG_CRT_SAVE (LogLevel.DEBUG, R.string.msg_crt_save),
MSG_CRT_SAVING (LogLevel.DEBUG, R.string.msg_crt_saving),
MSG_CRT_SUCCESS (LogLevel.OK, R.string.msg_crt_success),

View File

@@ -31,6 +31,7 @@ public class SignEncryptResult extends OperationResult {
public static final int RESULT_PENDING = RESULT_ERROR + 8;
public PgpSignEncryptResult getPending() {
for (PgpSignEncryptResult sub : mResults) {
if (sub.isPending()) {