mirror of
https://github.com/moparisthebest/open-keychain
synced 2025-02-17 07:30:14 -05:00
parent
6536ca825b
commit
344bc1736d
@ -20,6 +20,8 @@ package org.sufficientlysecure.keychain.pgp;
|
|||||||
|
|
||||||
import org.spongycastle.bcpg.SignatureSubpacket;
|
import org.spongycastle.bcpg.SignatureSubpacket;
|
||||||
import org.spongycastle.bcpg.SignatureSubpacketTags;
|
import org.spongycastle.bcpg.SignatureSubpacketTags;
|
||||||
|
import org.spongycastle.bcpg.sig.Exportable;
|
||||||
|
import org.spongycastle.bcpg.sig.Revocable;
|
||||||
import org.spongycastle.bcpg.sig.RevocationReason;
|
import org.spongycastle.bcpg.sig.RevocationReason;
|
||||||
import org.spongycastle.openpgp.PGPException;
|
import org.spongycastle.openpgp.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||||
@ -218,12 +220,23 @@ public class WrappedSignature {
|
|||||||
return new WrappedSignature(signatures.get(0));
|
return new WrappedSignature(signatures.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns true if this certificate is revocable in general. */
|
||||||
|
public boolean isRevokable () {
|
||||||
|
// If nothing is specified, the packet is considered revocable
|
||||||
|
if (mSig.getHashedSubPackets() == null
|
||||||
|
|| !mSig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.REVOCABLE)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
SignatureSubpacket p = mSig.getHashedSubPackets().getSubpacket(SignatureSubpacketTags.REVOCABLE);
|
||||||
|
return ((Revocable) p).isRevocable();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isLocal() {
|
public boolean isLocal() {
|
||||||
if (mSig.getHashedSubPackets() == null
|
if (mSig.getHashedSubPackets() == null
|
||||||
|| !mSig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.EXPORTABLE)) {
|
|| !mSig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.EXPORTABLE)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SignatureSubpacket p = mSig.getHashedSubPackets().getSubpacket(SignatureSubpacketTags.EXPORTABLE);
|
SignatureSubpacket p = mSig.getHashedSubPackets().getSubpacket(SignatureSubpacketTags.EXPORTABLE);
|
||||||
return p.getData()[0] == 0;
|
return ((Exportable) p).isExportable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -450,47 +450,67 @@ public class ProviderHelper {
|
|||||||
for (WrappedSignature cert : new IterableIterator<WrappedSignature>(
|
for (WrappedSignature cert : new IterableIterator<WrappedSignature>(
|
||||||
masterKey.getSignaturesForRawId(rawUserId))) {
|
masterKey.getSignaturesForRawId(rawUserId))) {
|
||||||
long certId = cert.getKeyId();
|
long certId = cert.getKeyId();
|
||||||
|
// self signature
|
||||||
|
if (certId == masterKeyId) {
|
||||||
|
|
||||||
|
// NOTE self-certificates are already verified during canonicalization,
|
||||||
|
// AND we know there is at most one cert plus at most one revocation
|
||||||
|
if (!cert.isRevocation()) {
|
||||||
|
item.selfCert = cert;
|
||||||
|
item.isPrimary = cert.isPrimaryUserId();
|
||||||
|
} else {
|
||||||
|
item.isRevoked = true;
|
||||||
|
log(LogType.MSG_IP_UID_REVOKED);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// do we have a trusted key for this?
|
||||||
|
if (trustedKeys.indexOfKey(certId) < 0) {
|
||||||
|
unknownCerts += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify signatures from known private keys
|
||||||
|
CanonicalizedPublicKey trustedKey = trustedKeys.get(certId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// self signature
|
cert.init(trustedKey);
|
||||||
if (certId == masterKeyId) {
|
// if it doesn't certify, leave a note and skip
|
||||||
|
if ( ! cert.verifySignature(masterKey, rawUserId)) {
|
||||||
// NOTE self-certificates are already verified during canonicalization,
|
log(LogType.MSG_IP_UID_CERT_BAD);
|
||||||
// AND we know there is at most one cert plus at most one revocation
|
|
||||||
if (!cert.isRevocation()) {
|
|
||||||
item.selfCert = cert;
|
|
||||||
item.isPrimary = cert.isPrimaryUserId();
|
|
||||||
} else {
|
|
||||||
item.isRevoked = true;
|
|
||||||
log(LogType.MSG_IP_UID_REVOKED);
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify signatures from known private keys
|
log(cert.isRevocation()
|
||||||
if (trustedKeys.indexOfKey(certId) >= 0) {
|
? LogType.MSG_IP_UID_CERT_GOOD_REVOKE
|
||||||
CanonicalizedPublicKey trustedKey = trustedKeys.get(certId);
|
: LogType.MSG_IP_UID_CERT_GOOD,
|
||||||
if (cert.isRevocation()) {
|
KeyFormattingUtils.convertKeyIdToHexShort(trustedKey.getKeyId())
|
||||||
// skip for now
|
);
|
||||||
|
|
||||||
|
// check if there is a previous certificate
|
||||||
|
WrappedSignature prev = item.trustedCerts.get(cert.getKeyId());
|
||||||
|
if (prev != null) {
|
||||||
|
// if it's newer, skip this one
|
||||||
|
if (prev.getCreationTime().after(cert.getCreationTime())) {
|
||||||
|
log(LogType.MSG_IP_UID_CERT_OLD);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cert.init(trustedKey);
|
// if the previous one was a non-revokable certification, no need to look further
|
||||||
if (cert.verifySignature(masterKey, rawUserId)) {
|
if (!prev.isRevocation() && !prev.isRevokable()) {
|
||||||
item.trustedCerts.add(cert);
|
log(LogType.MSG_IP_UID_CERT_NONREVOKE);
|
||||||
log(LogType.MSG_IP_UID_CERT_GOOD,
|
continue;
|
||||||
KeyFormattingUtils.convertKeyIdToHexShort(trustedKey.getKeyId())
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
log(LogType.MSG_IP_UID_CERT_BAD);
|
|
||||||
}
|
}
|
||||||
|
log(LogType.MSG_IP_UID_CERT_NEW);
|
||||||
}
|
}
|
||||||
|
item.trustedCerts.put(cert.getKeyId(), cert);
|
||||||
unknownCerts += 1;
|
|
||||||
|
|
||||||
} catch (PgpGeneralException e) {
|
} catch (PgpGeneralException e) {
|
||||||
log(LogType.MSG_IP_UID_CERT_ERROR,
|
log(LogType.MSG_IP_UID_CERT_ERROR,
|
||||||
KeyFormattingUtils.convertKeyIdToHex(cert.getKeyId()));
|
KeyFormattingUtils.convertKeyIdToHex(cert.getKeyId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unknownCerts > 0) {
|
if (unknownCerts > 0) {
|
||||||
@ -518,9 +538,18 @@ public class ProviderHelper {
|
|||||||
if (item.isRevoked) {
|
if (item.isRevoked) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < item.trustedCerts.size(); i++) {
|
|
||||||
|
// iterate over signatures
|
||||||
|
for (int i = 0; i < item.trustedCerts.size() ; i++) {
|
||||||
|
WrappedSignature sig = item.trustedCerts.valueAt(i);
|
||||||
|
// if it's a revocation
|
||||||
|
if (sig.isRevocation()) {
|
||||||
|
// don't further process it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// otherwise, build database operation
|
||||||
operations.add(buildCertOperations(
|
operations.add(buildCertOperations(
|
||||||
masterKeyId, userIdRank, item.trustedCerts.get(i), Certs.VERIFIED_SECRET));
|
masterKeyId, userIdRank, sig, Certs.VERIFIED_SECRET));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +597,7 @@ public class ProviderHelper {
|
|||||||
boolean isPrimary = false;
|
boolean isPrimary = false;
|
||||||
boolean isRevoked = false;
|
boolean isRevoked = false;
|
||||||
WrappedSignature selfCert;
|
WrappedSignature selfCert;
|
||||||
List<WrappedSignature> trustedCerts = new ArrayList<WrappedSignature>();
|
LongSparseArray<WrappedSignature> trustedCerts = new LongSparseArray<WrappedSignature>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(UserIdItem o) {
|
public int compareTo(UserIdItem o) {
|
||||||
|
@ -264,8 +264,12 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_IP_SUCCESS (LogLevel.OK, R.string.msg_ip_success),
|
MSG_IP_SUCCESS (LogLevel.OK, R.string.msg_ip_success),
|
||||||
MSG_IP_SUCCESS_IDENTICAL (LogLevel.OK, R.string.msg_ip_success_identical),
|
MSG_IP_SUCCESS_IDENTICAL (LogLevel.OK, R.string.msg_ip_success_identical),
|
||||||
MSG_IP_UID_CERT_BAD (LogLevel.WARN, R.string.msg_ip_uid_cert_bad),
|
MSG_IP_UID_CERT_BAD (LogLevel.WARN, R.string.msg_ip_uid_cert_bad),
|
||||||
MSG_IP_UID_CERT_ERROR (LogLevel.ERROR, R.string.msg_ip_uid_cert_error),
|
MSG_IP_UID_CERT_ERROR (LogLevel.WARN, R.string.msg_ip_uid_cert_error),
|
||||||
|
MSG_IP_UID_CERT_OLD (LogLevel.DEBUG, R.string.msg_ip_uid_cert_old),
|
||||||
|
MSG_IP_UID_CERT_NONREVOKE (LogLevel.DEBUG, R.string.msg_ip_uid_cert_nonrevoke),
|
||||||
|
MSG_IP_UID_CERT_NEW (LogLevel.DEBUG, R.string.msg_ip_uid_cert_new),
|
||||||
MSG_IP_UID_CERT_GOOD (LogLevel.DEBUG, R.string.msg_ip_uid_cert_good),
|
MSG_IP_UID_CERT_GOOD (LogLevel.DEBUG, R.string.msg_ip_uid_cert_good),
|
||||||
|
MSG_IP_UID_CERT_GOOD_REVOKE (LogLevel.DEBUG, R.string.msg_ip_uid_cert_good_revoke),
|
||||||
MSG_IP_UID_CERTS_UNKNOWN (LogLevel.DEBUG, R.plurals.msg_ip_uid_certs_unknown),
|
MSG_IP_UID_CERTS_UNKNOWN (LogLevel.DEBUG, R.plurals.msg_ip_uid_certs_unknown),
|
||||||
MSG_IP_UID_CLASSIFYING_ZERO (LogLevel.DEBUG, R.string.msg_ip_uid_classifying_zero),
|
MSG_IP_UID_CLASSIFYING_ZERO (LogLevel.DEBUG, R.string.msg_ip_uid_classifying_zero),
|
||||||
MSG_IP_UID_CLASSIFYING (LogLevel.DEBUG, R.plurals.msg_ip_uid_classifying),
|
MSG_IP_UID_CLASSIFYING (LogLevel.DEBUG, R.plurals.msg_ip_uid_classifying),
|
||||||
|
@ -580,7 +580,11 @@
|
|||||||
<string name="msg_ip_reinsert_secret">"Re-inserting secret key"</string>
|
<string name="msg_ip_reinsert_secret">"Re-inserting secret key"</string>
|
||||||
<string name="msg_ip_uid_cert_bad">"Encountered bad certificate!"</string>
|
<string name="msg_ip_uid_cert_bad">"Encountered bad certificate!"</string>
|
||||||
<string name="msg_ip_uid_cert_error">"Error processing certificate!"</string>
|
<string name="msg_ip_uid_cert_error">"Error processing certificate!"</string>
|
||||||
<string name="msg_ip_uid_cert_good">"User id is certified by %1$s"</string>
|
<string name="msg_ip_uid_cert_nonrevoke">"Already have a non-revokable certificate, skipping."</string>
|
||||||
|
<string name="msg_ip_uid_cert_old">"Certificate is older than previous, skipping."</string>
|
||||||
|
<string name="msg_ip_uid_cert_new">"Certificate is more recent, replacing previous."</string>
|
||||||
|
<string name="msg_ip_uid_cert_good">"Found good certificate by %1$s"</string>
|
||||||
|
<string name="msg_ip_uid_cert_good_revoke">"Found good certificate revocation by %1$s"</string>
|
||||||
<plurals name="msg_ip_uid_certs_unknown">
|
<plurals name="msg_ip_uid_certs_unknown">
|
||||||
<item quantity="one">"Ignoring one certificate issued by an unknown public key"</item>
|
<item quantity="one">"Ignoring one certificate issued by an unknown public key"</item>
|
||||||
<item quantity="other">"Ignoring %s certificates issued by unknown public keys"</item>
|
<item quantity="other">"Ignoring %s certificates issued by unknown public keys"</item>
|
||||||
|
Loading…
Reference in New Issue
Block a user