diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/KeyType.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/KeyType.java index 59c0dc89e..da27a3ccb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/KeyType.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/KeyType.java @@ -20,20 +20,22 @@ package org.sufficientlysecure.keychain.securitytoken; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; public enum KeyType { - SIGN(0, 0xB6, 0xCE, 0xC7), - ENCRYPT(1, 0xB8, 0xCF, 0xC8), - AUTH(2, 0xA4, 0xD0, 0xC9),; + SIGN(0, 0xB6, 0xCE, 0xC7, 0xC1), + ENCRYPT(1, 0xB8, 0xCF, 0xC8, 0xC2), + AUTH(2, 0xA4, 0xD0, 0xC9, 0xC3); private final int mIdx; private final int mSlot; private final int mTimestampObjectId; private final int mFingerprintObjectId; + private final int mAlgoAttributeSlot; - KeyType(final int idx, final int slot, final int timestampObjectId, final int fingerprintObjectId) { + KeyType(int idx, int slot, int timestampObjectId, int fingerprintObjectId, int algoAttributeSlot) { this.mIdx = idx; this.mSlot = slot; this.mTimestampObjectId = timestampObjectId; this.mFingerprintObjectId = fingerprintObjectId; + this.mAlgoAttributeSlot = algoAttributeSlot; } public static KeyType from(final CanonicalizedSecretKey key) { @@ -62,4 +64,8 @@ public enum KeyType { public int getFingerprintObjectId() { return mFingerprintObjectId; } + + public int getAlgoAttributeSlot() { + return mAlgoAttributeSlot; + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenConnection.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenConnection.java index 70fff4866..644c992ec 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenConnection.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenConnection.java @@ -193,8 +193,7 @@ public class SecurityTokenConnection { throw new CardException("Initialization failed!", response.getSw()); } - OpenPgpCapabilities openPgpCapabilities = new OpenPgpCapabilities(getData(0x00, 0x6E)); - setConnectionCapabilities(openPgpCapabilities); + refreshConnectionCapabilities(); mPw1ValidatedForSignature = false; mPw1ValidatedForDecrypt = false; @@ -235,6 +234,13 @@ public class SecurityTokenConnection { tokenType = TokenType.UNKNOWN; } + private void refreshConnectionCapabilities() throws IOException { + byte[] rawOpenPgpCapabilities = getData(0x00, 0x6E); + + OpenPgpCapabilities openPgpCapabilities = new OpenPgpCapabilities(rawOpenPgpCapabilities); + setConnectionCapabilities(openPgpCapabilities); + } + @VisibleForTesting void setConnectionCapabilities(OpenPgpCapabilities openPgpCapabilities) throws IOException { this.mOpenPgpCapabilities = openPgpCapabilities; @@ -493,33 +499,13 @@ public class SecurityTokenConnection { } } - private void setKeyAttributes(Passphrase adminPin, final KeyType slot, final CanonicalizedSecretKey secretKey) - throws IOException { - - if (mOpenPgpCapabilities.isAttributesChangable()) { - int tag; - - if (slot == KeyType.SIGN) { - tag = 0xC1; - } else if (slot == KeyType.ENCRYPT) { - tag = 0xC2; - } else if (slot == KeyType.AUTH) { - tag = 0xC3; - } else { - throw new IOException("Unknown key for card."); - } - - try { - - putData(adminPin, tag, SecurityTokenUtils.attributesFromSecretKey(slot, secretKey)); - - mOpenPgpCapabilities.updateWithData(getData(0x00, tag)); - - } catch (PgpGeneralException e) { - throw new IOException("Key algorithm not supported by the security token."); - } - + private void setKeyAttributes(Passphrase adminPin, KeyType keyType, byte[] data) throws IOException { + if (!mOpenPgpCapabilities.isAttributesChangable()) { + return; } + + putData(adminPin, keyType.getAlgoAttributeSlot(), data); + refreshConnectionCapabilities(); } /** @@ -546,9 +532,11 @@ public class SecurityTokenConnection { try { secretKey.unlock(passphrase); - setKeyAttributes(adminPin, slot, secretKey); + setKeyAttributes(adminPin, slot, SecurityTokenUtils.attributesFromSecretKey(slot, secretKey, + mOpenPgpCapabilities.getFormatForKeyType(slot))); - switch (mOpenPgpCapabilities.getFormatForKeyType(slot).keyFormatType()) { + KeyFormat formatForKeyType = mOpenPgpCapabilities.getFormatForKeyType(slot); + switch (formatForKeyType.keyFormatType()) { case RSAKeyFormatType: if (!secretKey.isRSA()) { throw new IOException("Security Token not configured for RSA key."); @@ -561,7 +549,7 @@ public class SecurityTokenConnection { } keyBytes = SecurityTokenUtils.createRSAPrivKeyTemplate(crtSecretKey, slot, - (RSAKeyFormat) (mOpenPgpCapabilities.getFormatForKeyType(slot))); + (RSAKeyFormat) formatForKeyType); break; case ECKeyFormatType: @@ -574,7 +562,7 @@ public class SecurityTokenConnection { ecPublicKey = secretKey.getSecurityTokenECPublicKey(); keyBytes = SecurityTokenUtils.createECPrivKeyTemplate(ecSecretKey, ecPublicKey, slot, - (ECKeyFormat) (mOpenPgpCapabilities.getFormatForKeyType(slot))); + (ECKeyFormat) formatForKeyType); break; default: diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenUtils.java index 31df10576..35f12a317 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenUtils.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenUtils.java @@ -22,9 +22,6 @@ import org.bouncycastle.util.Arrays; import org.bouncycastle.util.encoders.Hex; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.securitytoken.ECKeyFormat; -import org.sufficientlysecure.keychain.securitytoken.RSAKeyFormat; -import org.sufficientlysecure.keychain.securitytoken.KeyType; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -33,8 +30,10 @@ import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPrivateCrtKey; + class SecurityTokenUtils { - static byte[] attributesFromSecretKey(final KeyType slot, final CanonicalizedSecretKey secretKey) throws IOException, PgpGeneralException { + static byte[] attributesFromSecretKey(KeyType slot, CanonicalizedSecretKey secretKey, KeyFormat formatForKeyType) + throws IOException, PgpGeneralException { if (secretKey.isRSA()) { final int mModulusLength = secretKey.getBitStrength(); final int mExponentLength = secretKey.getSecurityTokenRSASecretKey().getPublicExponent().bitLength(); @@ -46,7 +45,7 @@ class SecurityTokenUtils { attrs[i++] = (byte) (mModulusLength & 0xff); attrs[i++] = (byte) ((mExponentLength >> 8) & 0xff); attrs[i++] = (byte) (mExponentLength & 0xff); - attrs[i] = RSAKeyFormat.RSAAlgorithmFormat.CRT_WITH_MODULUS.getValue(); + attrs[i] = ((RSAKeyFormat) formatForKeyType).getAlgorithmFormat().getValue(); return attrs; } else if (secretKey.isEC()) {