Skip to content

Commit

Permalink
Separed SKS and AndroidKeyStore persistance
Browse files Browse the repository at this point in the history
  • Loading branch information
cyberphone committed Apr 13, 2019
1 parent 56b99f0 commit 9b97ca7
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,14 @@ public class AndroidSKSImplementation implements SecureKeyStore, Serializable, G
LinkedHashMap<Integer, PUKPolicy> pukPolicies = new LinkedHashMap<Integer, PUKPolicy>();

X509Certificate[] deviceCertificatePath;
PrivateKey attestationKey;
private transient PrivateKey attestationKey; // Hardware backed do not serialize

private static final String SKS_DEBUG = "SKS"; // Android SKS debug constant

static final String ANDROID_KEYSTORE = "AndroidKeyStore"; // Hardware backed keys
AndroidSKSImplementation() {
}

AndroidSKSImplementation(X509Certificate[] deviceCertificatePath, PrivateKey attestationKey) {
void setDeviceCredentials(X509Certificate[] deviceCertificatePath, PrivateKey attestationKey) {
this.deviceCertificatePath = deviceCertificatePath;
this.attestationKey = attestationKey;
}
Expand Down Expand Up @@ -1057,22 +1058,6 @@ static Algorithm addAlgorithm(String uri, String jceName, int mask) {
(byte)0x22, (byte)0xA8, (byte)0x87, (byte)0x64, (byte)0xD0, (byte)0x36, (byte)0xAF, (byte)0xD3,
(byte)0x69, (byte)0xAC, (byte)0xCA, (byte)0xCB, (byte)0x1A, (byte)0x96});

addAlgorithm("https://webpki.github.io/sks/algorithm#ec.brainpool.p256r1",
"brainpoolP256r1",
ALG_EC_KEY | ALG_KEY_GEN).addEcCurve (32, new byte[]
{(byte)0x30, (byte)0x5A, (byte)0x30, (byte)0x14, (byte)0x06, (byte)0x07, (byte)0x2A, (byte)0x86,
(byte)0x48, (byte)0xCE, (byte)0x3D, (byte)0x02, (byte)0x01, (byte)0x06, (byte)0x09, (byte)0x2B,
(byte)0x24, (byte)0x03, (byte)0x03, (byte)0x02, (byte)0x08, (byte)0x01, (byte)0x01, (byte)0x07,
(byte)0x03, (byte)0x42, (byte)0x00, (byte)0x04, (byte)0x26, (byte)0x3C, (byte)0x91, (byte)0x3F,
(byte)0x6B, (byte)0x91, (byte)0x10, (byte)0x6F, (byte)0xE4, (byte)0xA2, (byte)0x2D, (byte)0xA4,
(byte)0xBB, (byte)0xAB, (byte)0xCE, (byte)0x9E, (byte)0x41, (byte)0x01, (byte)0x0B, (byte)0xB0,
(byte)0xC3, (byte)0x84, (byte)0xEF, (byte)0x35, (byte)0x0D, (byte)0x66, (byte)0xEE, (byte)0x0C,
(byte)0xEC, (byte)0x60, (byte)0xB6, (byte)0xF5, (byte)0x54, (byte)0x54, (byte)0x27, (byte)0x2A,
(byte)0x1D, (byte)0x07, (byte)0x61, (byte)0xB0, (byte)0xC3, (byte)0x01, (byte)0xE8, (byte)0xCB,
(byte)0x52, (byte)0xF5, (byte)0x03, (byte)0xC1, (byte)0x0C, (byte)0x3F, (byte)0xF0, (byte)0x97,
(byte)0xCD, (byte)0xC9, (byte)0x45, (byte)0xF3, (byte)0x21, (byte)0xC5, (byte)0xCF, (byte)0x41,
(byte)0x17, (byte)0xF3, (byte)0x3A, (byte)0xB4});

for (short rsa_size : SKS_DEFAULT_RSA_SUPPORT) {
addAlgorithm("https://webpki.github.io/sks/algorithm#rsa" + rsa_size,
null, ALG_RSA_KEY | ALG_KEY_GEN | rsa_size);
Expand Down
83 changes: 59 additions & 24 deletions app/src/main/java/org/webpki/mobile/android/sks/SKSStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.SecureRandom;

import java.security.cert.X509Certificate;
Expand All @@ -46,48 +47,81 @@

@SuppressWarnings("deprecation")
public abstract class SKSStore {
private static final String PERSISTENCE_SKS = "SKS"; // SKS persistence file

private static final String DEVICE_KEY_NAME = "device";
private static final String PERSISTENCE_SKS = "SKS"; // SKS persistence file

private static final String DEVICE_KEY_NAME = "device";

private static final String LOG_NAME = "ANDROID/KS";

private static final String ANDROID_KEYSTORE = "AndroidKeyStore"; // Hardware backed keys


private static AndroidSKSImplementation sks;

private static HashSet<String> supportedAlgorithms;

public static synchronized AndroidSKSImplementation createSKS(String callerForLog,
Context caller,
boolean saveIfNew) {
if (sks == null) {
static KeyStore hardwareBacked;

static {
try {
hardwareBacked = KeyStore.getInstance(ANDROID_KEYSTORE);
hardwareBacked.load(null);
} catch (Exception e) {
Log.e(LOG_NAME, e.getMessage());
throw new RuntimeException();
}
}

static X509Certificate deviceCertificate;
static PrivateKey deviceKey;

static void getDeviceCredentials(String androidId) {
if (deviceCertificate == null) {
try {
sks = (AndroidSKSImplementation) new ObjectInputStream(
caller.openFileInput(PERSISTENCE_SKS)).readObject();
getAlgorithms();
Log.i(callerForLog, "SKS found, restoring it");
} catch (Exception e) {
Log.i(callerForLog, "SKS not found, recreating it");
try {
String androidId = Settings.Secure.getString(caller.getContentResolver(),
Settings.Secure.ANDROID_ID);
if (hardwareBacked.isKeyEntry(DEVICE_KEY_NAME)) {
deviceKey = (PrivateKey) hardwareBacked.getKey(DEVICE_KEY_NAME, null);
Log.i(LOG_NAME, "Had a key already");
} else {
byte[] serial = new byte[8];
new SecureRandom().nextBytes(serial);
KeyPairGenerator kpg = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_EC, AndroidSKSImplementation.ANDROID_KEYSTORE);
KeyProperties.KEY_ALGORITHM_EC, ANDROID_KEYSTORE);
kpg.initialize(new KeyGenParameterSpec.Builder(
DEVICE_KEY_NAME, KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
DEVICE_KEY_NAME, KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
.setDigests(KeyProperties.DIGEST_SHA256)
.setCertificateSerialNumber(new BigInteger(1, serial))
.setCertificateNotBefore(new Date(System.currentTimeMillis() - 600000L))
.setCertificateSubject(new X500Principal("serialNumber=" +
(androidId == null ? "N/A" : androidId) + ",CN=Android SKS"))
.build());
.build());
KeyPair keyPair = kpg.generateKeyPair();
KeyStore keyStore = KeyStore.getInstance(AndroidSKSImplementation.ANDROID_KEYSTORE);
keyStore.load(null);
deviceKey = keyPair.getPrivate();
Log.i(LOG_NAME, "Created a key");
}
deviceCertificate = (X509Certificate) hardwareBacked.getCertificate(DEVICE_KEY_NAME);
} catch (Exception e) {
Log.e(LOG_NAME, e.getMessage());
}
}
}

sks = new AndroidSKSImplementation(
new X509Certificate[]{(X509Certificate) keyStore.getCertificate(DEVICE_KEY_NAME)},
keyPair.getPrivate());
public static synchronized AndroidSKSImplementation createSKS(String callerForLog,
Context caller,
boolean saveIfNew) {
getDeviceCredentials(Settings.Secure.getString(caller.getContentResolver(),
Settings.Secure.ANDROID_ID));
if (sks == null) {
try {
sks = (AndroidSKSImplementation) new ObjectInputStream(
caller.openFileInput(PERSISTENCE_SKS)).readObject();
getAlgorithms();
Log.i(callerForLog, "SKS found, restoring it");
} catch (Exception e) {
Log.i(callerForLog, "SKS not found, recreating it");
try {
sks = new AndroidSKSImplementation();
if (saveIfNew) {
serializeSKS(callerForLog, caller);
}
Expand All @@ -96,6 +130,7 @@ public static synchronized AndroidSKSImplementation createSKS(String callerForLo
Log.e(callerForLog, e2.getMessage());
}
}
sks.setDeviceCredentials(new X509Certificate[]{deviceCertificate}, deviceKey);
}
return sks;
}
Expand All @@ -114,7 +149,7 @@ public static synchronized void serializeSKS(String callerForLog, Context caller
oos.writeObject(sks);
oos.close();
} catch (Exception e) {
Log.e(callerForLog, "Couldn't write SKS");
Log.e(callerForLog, "Couldn't write SKS: " + e.getMessage());
}
}
}
Expand Down

0 comments on commit 9b97ca7

Please sign in to comment.