introduce handling of notation direct key signatures, and experimental pin notation packet

This commit is contained in:
Vincent Breitmoser 2014-12-30 00:44:12 +01:00
parent 576e6fd0cc
commit c7b0b650c1
13 changed files with 126 additions and 24 deletions

View File

@ -370,13 +370,15 @@ public abstract class OperationResult implements Parcelable {
MSG_KC_ERROR_MASTER_ALGO (LogLevel.ERROR, R.string.msg_kc_error_master_algo),
MSG_KC_ERROR_DUP_KEY (LogLevel.ERROR, R.string.msg_kc_error_dup_key),
MSG_KC_MASTER (LogLevel.DEBUG, R.string.msg_kc_master),
MSG_KC_BAD_TYPE(LogLevel.WARN, R.string.msg_kc_bad_type),
MSG_KC_REVOKE_BAD_ERR (LogLevel.WARN, R.string.msg_kc_revoke_bad_err),
MSG_KC_REVOKE_BAD_LOCAL (LogLevel.WARN, R.string.msg_kc_revoke_bad_local),
MSG_KC_REVOKE_BAD_TIME (LogLevel.WARN, R.string.msg_kc_revoke_bad_time),
MSG_KC_REVOKE_BAD_TYPE (LogLevel.WARN, R.string.msg_kc_revoke_bad_type),
MSG_KC_REVOKE_BAD_TYPE_UID (LogLevel.WARN, R.string.msg_kc_revoke_bad_type_uid),
MSG_KC_REVOKE_BAD (LogLevel.WARN, R.string.msg_kc_revoke_bad),
MSG_KC_REVOKE_DUP (LogLevel.DEBUG, R.string.msg_kc_revoke_dup),
MSG_KC_NOTATION_DUP (LogLevel.DEBUG, R.string.msg_kc_notation_dup),
MSG_KC_NOTATION_EMPTY (LogLevel.DEBUG, R.string.msg_kc_notation_empty),
MSG_KC_SUB (LogLevel.DEBUG, R.string.msg_kc_sub),
MSG_KC_SUB_BAD(LogLevel.WARN, R.string.msg_kc_sub_bad),
MSG_KC_SUB_BAD_ERR(LogLevel.WARN, R.string.msg_kc_sub_bad_err),

View File

@ -34,6 +34,7 @@ import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.PGPSignatureGenerator;
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
@ -877,7 +878,8 @@ public class PgpKeyOperation {
log.add(LogType.MSG_MF_PASSPHRASE, indent);
indent += 1;
sKR = applyNewUnlock(sKR, masterPublicKey, passphrase, saveParcel.mNewUnlock, log, indent);
sKR = applyNewUnlock(sKR, masterPublicKey, masterPrivateKey,
passphrase, saveParcel.mNewUnlock, log, indent);
if (sKR == null) {
// The error has been logged above, just return a bad state
return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null);
@ -909,19 +911,60 @@ public class PgpKeyOperation {
private static PGPSecretKeyRing applyNewUnlock(
PGPSecretKeyRing sKR,
PGPPublicKey masterPublicKey,
PGPPrivateKey masterPrivateKey,
String passphrase,
ChangeUnlockParcel newUnlock,
OperationLog log, int indent) throws PGPException {
if (newUnlock.mNewPassphrase != null) {
return applyNewPassphrase(sKR, masterPublicKey, passphrase, newUnlock.mNewPassphrase, log, indent);
sKR = applyNewPassphrase(sKR, masterPublicKey, passphrase, newUnlock.mNewPassphrase, log, indent);
// add packet with EMPTY notation data (updates old one, but will be stripped later)
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), HashAlgorithmTags.SHA512)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
{ // set subpackets
PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
hashedPacketsGen.setExportable(false, false);
sGen.setHashedSubpackets(hashedPacketsGen.generate());
}
sGen.init(PGPSignature.DIRECT_KEY, masterPrivateKey);
PGPSignature emptySig = sGen.generateCertification(masterPublicKey);
masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, emptySig);
PGPSecretKey.replacePublicKey(sKR.getSecretKey(), masterPublicKey);
return sKR;
}
if (newUnlock.mNewPin != null) {
sKR = applyNewPassphrase(sKR, masterPublicKey, passphrase, newUnlock.mNewPin, log, indent);
// add packet with EMPTY notation data (updates old one, but will be stripped later)
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), HashAlgorithmTags.SHA512)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
{ // set subpackets
PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
hashedPacketsGen.setExportable(false, false);
hashedPacketsGen.setNotationData(false, false, "pin@unlock.sufficientlysecure.org", "1");
sGen.setHashedSubpackets(hashedPacketsGen.generate());
}
sGen.init(PGPSignature.DIRECT_KEY, masterPrivateKey);
PGPSignature emptySig = sGen.generateCertification(masterPublicKey);
masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, emptySig);
PGPSecretKey.replacePublicKey(sKR.getSecretKey(), masterPublicKey);
return sKR;
}
throw new UnsupportedOperationException("PIN passphrases not yet implemented!");
}
private static PGPSecretKeyRing applyNewPassphrase(
PGPSecretKeyRing sKR,
PGPPublicKey masterPublicKey,

View File

@ -41,7 +41,6 @@ import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Utf8Util;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -302,6 +301,7 @@ public class UncachedKeyRing {
PGPPublicKey modified = masterKey;
PGPSignature revocation = null;
PGPSignature notation = null;
for (PGPSignature zert : new IterableIterator<PGPSignature>(masterKey.getKeySignatures())) {
int type = zert.getSignatureType();
@ -318,9 +318,9 @@ public class UncachedKeyRing {
}
WrappedSignature cert = new WrappedSignature(zert);
if (type != PGPSignature.KEY_REVOCATION) {
if (type != PGPSignature.KEY_REVOCATION && type != PGPSignature.DIRECT_KEY) {
// Unknown type, just remove
log.add(LogType.MSG_KC_REVOKE_BAD_TYPE, indent, "0x" + Integer.toString(type, 16));
log.add(LogType.MSG_KC_BAD_TYPE, indent, "0x" + Integer.toString(type, 16));
modified = PGPPublicKey.removeCertification(modified, zert);
badCerts += 1;
continue;
@ -334,14 +334,6 @@ public class UncachedKeyRing {
continue;
}
if (cert.isLocal()) {
// Remove revocation certs with "local" flag
log.add(LogType.MSG_KC_REVOKE_BAD_LOCAL, indent);
modified = PGPPublicKey.removeCertification(modified, zert);
badCerts += 1;
continue;
}
try {
cert.init(masterKey);
if (!cert.verifySignature(masterKey)) {
@ -357,6 +349,41 @@ public class UncachedKeyRing {
continue;
}
if (cert.isLocal()) {
// Remove revocation certs with "local" flag
log.add(LogType.MSG_KC_REVOKE_BAD_LOCAL, indent);
modified = PGPPublicKey.removeCertification(modified, zert);
badCerts += 1;
continue;
}
// special case: direct key signatures!
if (cert.getSignatureType() == PGPSignature.DIRECT_KEY) {
// must be local, otherwise strip!
if (!cert.isLocal()) {
log.add(LogType.MSG_KC_BAD_TYPE, indent);
modified = PGPPublicKey.removeCertification(modified, zert);
badCerts += 1;
continue;
}
// first notation? fine then.
if (notation == null) {
notation = zert;
// more notations? at least one is superfluous, then.
} else if (notation.getCreationTime().before(zert.getCreationTime())) {
log.add(LogType.MSG_KC_NOTATION_DUP, indent);
modified = PGPPublicKey.removeCertification(modified, notation);
redundantCerts += 1;
notation = zert;
} else {
log.add(LogType.MSG_KC_NOTATION_DUP, indent);
modified = PGPPublicKey.removeCertification(modified, zert);
redundantCerts += 1;
}
continue;
}
// first revocation? fine then.
if (revocation == null) {
revocation = zert;
@ -373,6 +400,16 @@ public class UncachedKeyRing {
}
}
// If we have a notation packet, check if there is even any data in it?
if (notation != null) {
// If there isn't, might as well strip it
if (new WrappedSignature(notation).getNotation().isEmpty()) {
log.add(LogType.MSG_KC_NOTATION_EMPTY, indent);
modified = PGPPublicKey.removeCertification(modified, notation);
redundantCerts += 1;
}
}
ArrayList<String> processedUserIds = new ArrayList<String>();
for (byte[] rawUserId : new IterableIterator<byte[]>(masterKey.getRawUserIDs())) {
String userId = Utf8Util.fromUTF8ByteArrayReplaceBadEncoding(rawUserId);

View File

@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.bcpg.SignatureSubpacket;
import org.spongycastle.bcpg.SignatureSubpacketTags;
import org.spongycastle.bcpg.sig.Exportable;
import org.spongycastle.bcpg.sig.NotationData;
import org.spongycastle.bcpg.sig.Revocable;
import org.spongycastle.bcpg.sig.RevocationReason;
import org.spongycastle.openpgp.PGPException;
@ -37,6 +38,7 @@ import java.io.IOException;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
/** OpenKeychain wrapper around PGPSignature objects.
*
@ -239,4 +241,20 @@ public class WrappedSignature {
SignatureSubpacket p = mSig.getHashedSubPackets().getSubpacket(SignatureSubpacketTags.EXPORTABLE);
return ! ((Exportable) p).isExportable();
}
public HashMap<String,byte[]> getNotation() {
HashMap<String,byte[]> result = new HashMap<String,byte[]>();
// If there is any notation data
if (mSig.getHashedSubPackets() != null
&& mSig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.NOTATION_DATA)) {
// Iterate over notation data
for (NotationData data : mSig.getHashedSubPackets().getNotationDataOccurrences()) {
result.put(data.getNotationName(), data.getNotationValueBytes());
}
}
return result;
}
}

View File

@ -607,7 +607,7 @@
<string name="msg_kc_revoke_bad_err">Entferne fehlerhaftes Schlüsselbund Widerrufszertifikat</string>
<string name="msg_kc_revoke_bad_local">Entferne Schlüsselbund Widerrufszertifikat mit \"Lokal\" Attribut</string>
<string name="msg_kc_revoke_bad_time">Entferne Schlüsselbund Widerrufszertifikat mit zukünftigem Zeitstempel</string>
<string name="msg_kc_revoke_bad_type">Entferne Hauptschlüsselbeglaubigung unbekannter Art (%s)</string>
<string name="msg_kc_bad_type">Entferne Hauptschlüsselbeglaubigung unbekannter Art (%s)</string>
<string name="msg_kc_revoke_bad">Entferne fehlerhaftes Schlüsselbund Widerrufszertifikat</string>
<string name="msg_kc_revoke_dup">Entferne redundantes Schlüsselbund Widerrufszertifikat</string>
<string name="msg_kc_sub">Verarbeite Unterschlüssel %s</string>

View File

@ -652,7 +652,7 @@
<string name="msg_kc_revoke_bad_err">Eliminando certificado defectuoso de revocación de juego de claves</string>
<string name="msg_kc_revoke_bad_local">Eliminando certificado de revocación de juego de claves, con distintivo \"local\"</string>
<string name="msg_kc_revoke_bad_time">Eliminando certificado de revocación de juego de claves, con marca de tiempo futura</string>
<string name="msg_kc_revoke_bad_type">Eliminando certificado de clave maestra, de tipo desconocido (%s)</string>
<string name="msg_kc_bad_type">Eliminando certificado de clave maestra, de tipo desconocido (%s)</string>
<string name="msg_kc_revoke_bad_type_uid">Eliminando certificado de identificación de usuario en posición incorrecta</string>
<string name="msg_kc_revoke_bad">Eliminando certificado defectuoso de revocación de juego de claves</string>
<string name="msg_kc_revoke_dup">Eliminando certificado redundante de revocación de juego de claves </string>

View File

@ -652,7 +652,7 @@
<string name="msg_kc_revoke_bad_err">Suppression du mauvais certificat de révocation du trousseau</string>
<string name="msg_kc_revoke_bad_local">Suppression du certificat de révocation du trousseau ayant le drapeau « local »</string>
<string name="msg_kc_revoke_bad_time">Suppression du certificat de révocation du trousseau ayant une estampille temporelle dans le futur</string>
<string name="msg_kc_revoke_bad_type">Suppression du certificat de clef maîtresse de type inconnu (%s)</string>
<string name="msg_kc_bad_type">Suppression du certificat de clef maîtresse de type inconnu (%s)</string>
<string name="msg_kc_revoke_bad_type_uid">Suppression du certificat de l\'ID d\'utilisateur en mauvaise position</string>
<string name="msg_kc_revoke_bad">Suppression du mauvais certificat de révocation du trousseau</string>
<string name="msg_kc_revoke_dup"> Suppression du certificat redondant de révocation du trousseau</string>

View File

@ -602,7 +602,7 @@ Permetti accesso?\n\nATTENZIONE: Se non sai perche\' questo schermata e\' appars
<string name="msg_kc_revoke_bad_err">Rimozione di certificato di revoca del portachiavi corrotto</string>
<string name="msg_kc_revoke_bad_local">Rimozione certificato di revoca del portachiavi con caratteristica \"locale\"</string>
<string name="msg_kc_revoke_bad_time">Rimozione certificato di revoca del portachiavi con marca temporale futura</string>
<string name="msg_kc_revoke_bad_type">Rimozione certificato della chiave principale di tipo sconosciuto (%s)</string>
<string name="msg_kc_bad_type">Rimozione certificato della chiave principale di tipo sconosciuto (%s)</string>
<string name="msg_kc_revoke_bad">Rimozione certificato di revoca del portachiavi corrotto</string>
<string name="msg_kc_revoke_dup">Rimozione certificato di revoca del portachiavi ridondante</string>
<string name="msg_kc_sub">Elaborazione sottochiave %s</string>

View File

@ -618,7 +618,7 @@
<string name="msg_kc_revoke_bad_err">問題のある鍵輪の破棄証明を破棄中</string>
<string name="msg_kc_revoke_bad_local">鍵輪のローカルフラグ付き破棄証明を破棄中</string>
<string name="msg_kc_revoke_bad_time">鍵輪の未来にタイムスタンプがある破棄証明を破棄中</string>
<string name="msg_kc_revoke_bad_type">問題のある主鍵の不明な型 (%s) の証明を破棄中</string>
<string name="msg_kc_bad_type">問題のある主鍵の不明な型 (%s) の証明を破棄中</string>
<string name="msg_kc_revoke_bad_type_uid">不正な位置のユーザID検証を破棄中</string>
<string name="msg_kc_revoke_bad">問題のある鍵輪の破棄証明を破棄中</string>
<string name="msg_kc_revoke_dup">重複している鍵輪の破棄証明を破棄中</string>

View File

@ -450,7 +450,7 @@
<string name="msg_kc_revoke_bad_err">Umikam slab certifikat za preklic zbirk ključev</string>
<string name="msg_kc_revoke_bad_local">Umikam certifikat za preklic zbirk ključev z oznako \"lokalno\"</string>
<string name="msg_kc_revoke_bad_time">Umikam certifikat za preklic zbirk ključev s časovno znamko v prihodnosti</string>
<string name="msg_kc_revoke_bad_type">Umikam certifikat glavnega ključa neznanega tipa (%s)</string>
<string name="msg_kc_bad_type">Umikam certifikat glavnega ključa neznanega tipa (%s)</string>
<string name="msg_kc_revoke_bad">Umikam slab certifikat za preklic zbirk ključev</string>
<string name="msg_kc_revoke_dup">Umikam odvečen certifikat za preklic zbirk ključev</string>
<string name="msg_kc_sub">Obdelujem podključ %s</string>

View File

@ -672,7 +672,7 @@
<string name="msg_kc_revoke_bad_err">Уклањам лош сертификат опозива привеска</string>
<string name="msg_kc_revoke_bad_local">Уклањам сертификат опозива привеска са заставицом „локални“</string>
<string name="msg_kc_revoke_bad_time">Уклањам сертификат опозива привеска са временском ознаком у будућности</string>
<string name="msg_kc_revoke_bad_type">Уклањам сертификат главног кључа непознатог типа (%s)</string>
<string name="msg_kc_bad_type">Уклањам сертификат главног кључа непознатог типа (%s)</string>
<string name="msg_kc_revoke_bad_type_uid">Уклањам сертификат корисничког ИД-а са погрешног места</string>
<string name="msg_kc_revoke_bad">Уклањам лош сертификат опозива привеска</string>
<string name="msg_kc_revoke_dup">Уклањам сувишни сертификат опозива привеска</string>

View File

@ -573,7 +573,7 @@
<string name="msg_kc_master">Bearbetar huvudnyckel</string>
<string name="msg_kc_revoke_bad_err">Tar bort dåligt återkallelsecertifikat för nyckelring</string>
<string name="msg_kc_revoke_bad_time">Tar bort återkallelsecertifikat för nyckelring med framtida tidstämpel</string>
<string name="msg_kc_revoke_bad_type">Tar bort huvudnyckelcertifikat av okänd typ (%s)</string>
<string name="msg_kc_bad_type">Tar bort huvudnyckelcertifikat av okänd typ (%s)</string>
<string name="msg_kc_revoke_bad">Tar bort dåligt återkallelsecertifikat för nyckelring</string>
<string name="msg_kc_revoke_dup">Tar bort överflödigt återkallelsecertifikat för nyckelring</string>
<string name="msg_kc_sub">Bearbetar undernyckel %s</string>

View File

@ -709,13 +709,15 @@
<string name="msg_kc_error_master_algo">"The master key uses an unknown (%s) algorithm!"</string>
<string name="msg_kc_error_dup_key">"Subkey %s occurs twice in keyring. Keyring is malformed, not importing!"</string>
<string name="msg_kc_master">"Processing master key"</string>
<string name="msg_kc_bad_type">"Removing master key certificate of unknown type (%s)"</string>
<string name="msg_kc_revoke_bad_err">"Removing bad keyring revocation certificate"</string>
<string name="msg_kc_revoke_bad_local">"Removing keyring revocation certificate with "local" flag"</string>
<string name="msg_kc_revoke_bad_time">"Removing keyring revocation certificate with future timestamp"</string>
<string name="msg_kc_revoke_bad_type">"Removing master key certificate of unknown type (%s)"</string>
<string name="msg_kc_revoke_bad_type_uid">"Removing user ID certificate in bad position"</string>
<string name="msg_kc_revoke_bad">"Removing bad keyring revocation certificate"</string>
<string name="msg_kc_revoke_dup">"Removing redundant keyring revocation certificate"</string>
<string name="msg_kc_notation_dup">"Removing redundant notation certificate"</string>
<string name="msg_kc_notation_empty">"Removing empty notation certificate"</string>
<string name="msg_kc_sub">"Processing subkey %s"</string>
<string name="msg_kc_sub_bad">"Removing invalid subkey binding certificate"</string>
<string name="msg_kc_sub_bad_err">"Removing bad subkey binding certificate"</string>