canonicalize: filter out future and local certificates
This commit is contained in:
@@ -2,6 +2,7 @@ package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||
import org.spongycastle.bcpg.S2K;
|
||||
import org.spongycastle.bcpg.SignatureSubpacketTags;
|
||||
import org.spongycastle.openpgp.PGPKeyRing;
|
||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||
import org.spongycastle.openpgp.PGPPublicKey;
|
||||
@@ -23,6 +24,7 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -178,6 +180,7 @@ public class UncachedKeyRing {
|
||||
*
|
||||
* More specifically:
|
||||
* - Remove all non-verifying self-certificates
|
||||
* - Remove all "future" self-certificates
|
||||
* - Remove all certificates flagged as "local"
|
||||
* - Remove all certificates which are superseded by a newer one on the same target
|
||||
*
|
||||
@@ -200,6 +203,8 @@ public class UncachedKeyRing {
|
||||
new String[]{PgpKeyHelper.convertKeyIdToHex(getMasterKeyId())}, indent);
|
||||
indent += 1;
|
||||
|
||||
final Date now = new Date();
|
||||
|
||||
int removedCerts = 0;
|
||||
|
||||
PGPPublicKeyRing ring = (PGPPublicKeyRing) mRing;
|
||||
@@ -215,6 +220,7 @@ public class UncachedKeyRing {
|
||||
PGPSignature revocation = null;
|
||||
for (PGPSignature zert : new IterableIterator<PGPSignature>(masterKey.getSignatures())) {
|
||||
int type = zert.getSignatureType();
|
||||
|
||||
// Disregard certifications on user ids, we will deal with those later
|
||||
if (type == PGPSignature.NO_CERTIFICATION
|
||||
|| type == PGPSignature.DEFAULT_CERTIFICATION
|
||||
@@ -227,7 +233,7 @@ public class UncachedKeyRing {
|
||||
|
||||
if (type != PGPSignature.KEY_REVOCATION) {
|
||||
// Unknown type, just remove
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_TYPE, new String[]{
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_TYPE, new String[]{
|
||||
"0x" + Integer.toString(type, 16)
|
||||
}, indent);
|
||||
modified = PGPPublicKey.removeCertification(modified, zert);
|
||||
@@ -235,6 +241,22 @@ public class UncachedKeyRing {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cert.getCreationTime().after(now)) {
|
||||
// Creation date in the future? No way!
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_TIME, null, indent);
|
||||
modified = PGPPublicKey.removeCertification(modified, zert);
|
||||
removedCerts += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cert.isLocal()) {
|
||||
// Creation date in the future? No way!
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_LOCAL, null, indent);
|
||||
modified = PGPPublicKey.removeCertification(modified, zert);
|
||||
removedCerts += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
cert.init(masterKey);
|
||||
if (!cert.verifySignature(masterKey)) {
|
||||
@@ -276,7 +298,38 @@ public class UncachedKeyRing {
|
||||
WrappedSignature cert = new WrappedSignature(zert);
|
||||
long certId = cert.getKeyId();
|
||||
|
||||
// If this is a foreign signature, never mind
|
||||
|
||||
int type = zert.getSignatureType();
|
||||
if (type != PGPSignature.DEFAULT_CERTIFICATION
|
||||
&& type != PGPSignature.NO_CERTIFICATION
|
||||
&& type != PGPSignature.CASUAL_CERTIFICATION
|
||||
&& type != PGPSignature.POSITIVE_CERTIFICATION
|
||||
&& type != PGPSignature.CERTIFICATION_REVOCATION) {
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_UID_BAD_TYPE,
|
||||
new String[] {
|
||||
"0x" + Integer.toString(zert.getSignatureType(), 16)
|
||||
}, indent);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, zert);
|
||||
removedCerts += 1;
|
||||
}
|
||||
|
||||
if (cert.getCreationTime().after(now)) {
|
||||
// Creation date in the future? No way!
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_TIME, null, indent);
|
||||
modified = PGPPublicKey.removeCertification(modified, zert);
|
||||
removedCerts += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cert.isLocal()) {
|
||||
// Creation date in the future? No way!
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_LOCAL, null, indent);
|
||||
modified = PGPPublicKey.removeCertification(modified, zert);
|
||||
removedCerts += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this is a foreign signature, never mind any further
|
||||
if (certId != masterKeyId) {
|
||||
continue;
|
||||
}
|
||||
@@ -299,7 +352,7 @@ public class UncachedKeyRing {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (zert.getSignatureType()) {
|
||||
switch (type) {
|
||||
case PGPSignature.DEFAULT_CERTIFICATION:
|
||||
case PGPSignature.NO_CERTIFICATION:
|
||||
case PGPSignature.CASUAL_CERTIFICATION:
|
||||
@@ -356,14 +409,6 @@ public class UncachedKeyRing {
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_UID_UNKNOWN_CERT,
|
||||
new String[] {
|
||||
"0x" + Integer.toString(zert.getSignatureType(), 16),
|
||||
userId
|
||||
}, indent);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, zert);
|
||||
removedCerts += 1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -401,6 +446,7 @@ public class UncachedKeyRing {
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_KEYID, null, indent);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type != PGPSignature.SUBKEY_BINDING && type != PGPSignature.SUBKEY_REVOCATION) {
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_TYPE, new String[]{
|
||||
"0x" + Integer.toString(type, 16)
|
||||
@@ -408,6 +454,18 @@ public class UncachedKeyRing {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cert.getCreationTime().after(now)) {
|
||||
// Creation date in the future? No way!
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_TIME, null, indent);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cert.isLocal()) {
|
||||
// Creation date in the future? No way!
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_SUB_BAD_LOCAL, null, indent);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == PGPSignature.SUBKEY_BINDING) {
|
||||
// TODO verify primary key binding signature for signing keys!
|
||||
|
||||
|
||||
@@ -178,4 +178,11 @@ public class WrappedSignature {
|
||||
return new WrappedSignature(signatures.get(0));
|
||||
}
|
||||
|
||||
public boolean isLocal() {
|
||||
if (!mSig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.EXPORTABLE)) {
|
||||
return false;
|
||||
}
|
||||
SignatureSubpacket p = mSig.getHashedSubPackets().getSubpacket(SignatureSubpacketTags.EXPORTABLE);
|
||||
return p.getData()[0] == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,12 +161,17 @@ public class OperationResultParcel implements Parcelable {
|
||||
MSG_KC_MASTER (R.string.msg_kc_master),
|
||||
MSG_KC_MASTER_SUCCESS (R.string.msg_kc_master_success),
|
||||
MSG_KC_REVOKE_BAD_ERR (R.string.msg_kc_revoke_bad_err),
|
||||
MSG_KC_REVOKE_BAD_LOCAL (R.string.msg_kc_revoke_bad_local),
|
||||
MSG_KC_REVOKE_BAD_TIME (R.string.msg_kc_revoke_bad_time),
|
||||
MSG_KC_REVOKE_BAD_TYPE (R.string.msg_kc_revoke_bad_type),
|
||||
MSG_KC_REVOKE_BAD (R.string.msg_kc_revoke_bad),
|
||||
MSG_KC_REVOKE_DUP (R.string.msg_kc_revoke_dup),
|
||||
MSG_KC_SUB (R.string.msg_kc_sub),
|
||||
MSG_KC_SUB_BAD_ERR(R.string.msg_kc_sub_bad_err),
|
||||
MSG_KC_SUB_BAD_KEYID(R.string.msg_kc_sub_bad_keyid),
|
||||
MSG_KC_SUB_BAD(R.string.msg_kc_sub_bad),
|
||||
MSG_KC_SUB_BAD_ERR(R.string.msg_kc_sub_bad_err),
|
||||
MSG_KC_SUB_BAD_LOCAL(R.string.msg_kc_sub_bad_local),
|
||||
MSG_KC_SUB_BAD_KEYID(R.string.msg_kc_sub_bad_keyid),
|
||||
MSG_KC_SUB_BAD_TIME(R.string.msg_kc_sub_bad_time),
|
||||
MSG_KC_SUB_BAD_TYPE(R.string.msg_kc_sub_bad_type),
|
||||
MSG_KC_SUB_NO_CERT(R.string.msg_kc_sub_no_cert),
|
||||
MSG_KC_SUB_REVOKE_BAD_ERR (R.string.msg_kc_sub_revoke_bad_err),
|
||||
@@ -176,11 +181,13 @@ public class OperationResultParcel implements Parcelable {
|
||||
MSG_KC_SUCCESS_REMOVED (R.string.msg_kc_success_removed),
|
||||
MSG_KC_SUCCESS (R.string.msg_kc_success),
|
||||
MSG_KC_UID_BAD_ERR (R.string.msg_kc_uid_bad_err),
|
||||
MSG_KC_UID_BAD_LOCAL (R.string.msg_kc_uid_bad_local),
|
||||
MSG_KC_UID_BAD_TIME (R.string.msg_kc_uid_bad_time),
|
||||
MSG_KC_UID_BAD_TYPE (R.string.msg_kc_uid_bad_type),
|
||||
MSG_KC_UID_BAD (R.string.msg_kc_uid_bad),
|
||||
MSG_KC_UID_DUP (R.string.msg_kc_uid_dup),
|
||||
MSG_KC_UID_REVOKE_DUP (R.string.msg_kc_uid_revoke_dup),
|
||||
MSG_KC_UID_REVOKE_OLD (R.string.msg_kc_uid_revoke_old),
|
||||
MSG_KC_UID_UNKNOWN_CERT (R.string.msg_kc_uid_unknown_cert),
|
||||
;
|
||||
|
||||
private final int mMsgId;
|
||||
|
||||
Reference in New Issue
Block a user