Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ else if (installedVersion.isGreaterThanOrEqualTo(new SdkVersion(9, 2, 0, false))
if (installedVersion.isLessThan(new SdkVersion(12, 0, 0, false))) {
updateFromBefore12_0_0();
}
if (installedVersion.isLessThan(new SdkVersion(13, 0, 2, false))) {
updateFromBefore13_0_2();
}
} catch (Exception e) {
SalesforceSDKLogger.e(
TAG,
Expand Down Expand Up @@ -306,4 +309,8 @@ private void updateFromBefore12_0_0() {
PushMessaging.setReRegistrationRequested(true);
}

private void updateFromBefore13_0_2() {
// Re-register all users for push notifications with new keys once push is setup
PushMessaging.setReRegistrationRequested(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@

import android.os.Build;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyInfo;
import android.security.keystore.KeyProperties;
import android.util.Base64;

import com.salesforce.androidsdk.util.SalesforceSDKLogger;

import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
Expand Down Expand Up @@ -253,6 +255,34 @@ private synchronized void createKeysIfNecessary(String algorithm, String name, i
}
}

/**
* Checks if the RSA key supports OAEP encryption padding.
*
* @param name Alias of the key to check.
* @return true if the key supports OAEP padding, false otherwise.
*/
public boolean keySupportsOAEPPadding(String name) {
try {
if (keyStore.containsAlias(name)) {
PrivateKey privateKey = (PrivateKey) keyStore.getKey(name, null);
KeyFactory keyFactory = KeyFactory.getInstance(privateKey.getAlgorithm(), ANDROID_KEYSTORE);
KeyInfo keyInfo = keyFactory.getKeySpec(privateKey, KeyInfo.class);
String[] encryptionPaddings = keyInfo.getEncryptionPaddings();

if (encryptionPaddings != null) {
for (String padding : encryptionPaddings) {
if (KeyProperties.ENCRYPTION_PADDING_RSA_OAEP.equals(padding)) {
return true;
}
}
}
}
} catch (Exception e) {
SalesforceSDKLogger.e(TAG, "Could not check key padding capabilities", e);
}
return false;
}

// For testing only - create key the way we used to before the 11.1.1 cipher change
synchronized void legacyCreateKeysIfNecessary(String algorithm, String name, int length) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,12 @@ private synchronized static String generateUniqueIdIfNoneStored(String name, int

// Encrypt and store unique id if it was just created, or if it had to be decrypted with old cipher mode
if (storeUniqueId) {
// Check if existing key supports OAEP padding, recreate if not
if (!KeyStoreWrapper.getInstance().keySupportsOAEPPadding(KEYSTORE_ALIAS)) {
SalesforceSDKLogger.i(TAG, "Key doesn't support OAEP padding, recreating key pair with OAEP support");
KeyStoreWrapper.getInstance().deleteKey(KEYSTORE_ALIAS);
}

final PublicKey publicKey = KeyStoreWrapper.getInstance().getRSAPublicKey(KEYSTORE_ALIAS);
final String encryptedKey = Encryptor.encryptWithRSA(publicKey, uniqueId, Encryptor.CipherMode.RSA_OAEP_SHA256);
storeInSharedPrefs(ID_PREFIX + name, encryptedKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,24 @@ class SalesforceSDKUpgradeManagerTest {
}

@Test
fun testUpgradeAfter12() {
fun testUpgradeFromBefore1302() {
// Set version to a version before 13.0.2
setVersion("12.2.0")

// Create public key for push notifications
KeyStoreWrapper.getInstance().getRSAPublicString(PushService.pushNotificationKeyName)

// Upgrade to latest
upgradeMgr.upgrade()

// Make sure re-registration is requested
Assert.assertTrue(PushMessaging.reRegistrationRequested)
}

@Test
fun testUpgradeAfter1302() {
// Set version to 12.0.0
setVersion("12.0.0")
setVersion("13.0.2")

// Create public key for push notifications
KeyStoreWrapper.getInstance().getRSAPublicString(PushService.pushNotificationKeyName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public class KeyStoreWrapperTest {

private static final String KEY_1 = "key_1";
private static final String KEY_2 = "key_2";
private static final String KEY_OAEP_TEST = "key_oaep_test";
private static final int RSA_LENGTH = 2048;

@Before
Expand All @@ -72,6 +73,7 @@ public void tearDown() throws Exception {
final KeyStoreWrapper keyStoreWrapper = KeyStoreWrapper.getInstance();
keyStoreWrapper.deleteKey(KEY_1);
keyStoreWrapper.deleteKey(KEY_2);
keyStoreWrapper.deleteKey(KEY_OAEP_TEST);
}

@Test
Expand Down Expand Up @@ -198,6 +200,27 @@ public void testDecryptDataEncryptedWithLegacyRSACipherForKeyCreatedBeforeUpgrad
tryNewOrUpgradedClientAgainstNewOrOldServer(false, false, false);
}

@Test
public void testKeySupportsOAEPPadding() {
final KeyStoreWrapper keyStoreWrapper = KeyStoreWrapper.getInstance();
Assert.assertNotNull("KeyStoreWrapper instance should not be null", keyStoreWrapper);

// Create a legacy key pair without OAEP padding support
keyStoreWrapper.legacyCreateKeysIfNecessary("RSA", KEY_OAEP_TEST, RSA_LENGTH);

// Verify the legacy key does NOT support OAEP padding
Assert.assertFalse("Legacy key should not support OAEP padding",
keyStoreWrapper.keySupportsOAEPPadding(KEY_OAEP_TEST));

// Delete the legacy key and create a modern key pair
keyStoreWrapper.deleteKey(KEY_OAEP_TEST);
keyStoreWrapper.getRSAPublicKey(KEY_OAEP_TEST, RSA_LENGTH); // This creates the key with modern spec

// Verify the modern key DOES support OAEP padding
Assert.assertTrue("Modern key should support OAEP padding",
keyStoreWrapper.keySupportsOAEPPadding(KEY_OAEP_TEST));
}

/**
* Helper method for tests for RSA cipher mode change
* @param newClient true means new client (key generated with new code), false means upgraded client (key generated the old way)
Expand Down
Loading