blob: da101f5bbf1aef8799c6ebc337a31413d8944762 [file] [log] [blame]
/*
*
* Copyright (c) 2013-2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.nestlabs.weave.security;
/**
* Utility methods and definitions for working with WeaveKeyIds.
*/
@SuppressWarnings("unused")
public final class WeaveKeyId {
// ===== Private Members =====
private static final int kKeyFlag_UseCurrentEpochKey = 0x80000000;
private static final int kKeyTypeModifier_IncorporatesEpochKey = 0x00001000;
private static final int kMask_KeyFlags = 0xF0000000;
private static final int kMask_AllDefinedFlags = kKeyFlag_UseCurrentEpochKey;
private static final int kMask_KeyType = 0x0FFFF000;
private static final int kMask_KeyNumber = 0x00000FFF;
private static final int kMask_RootKeyNumber = 0x00000C00;
private static final int kMask_EpochKeyNumber = 0x00000380;
private static final int kMask_AppGroupMasterKeyLocalId = 0x0000007F;
private static final int kShift_RootKeyNumber = 10;
private static final int kShift_EpochKeyNumber = 7;
private static final int kShift_AppGroupMasterKeyLocalId = 0;
// ===== Public Members =====
public static int getKeyType(int keyId) {
return keyId & kMask_KeyType;
}
public static int getRootKeyId(int keyId) {
if (!incorporatesRootKey(keyId)) {
throw new IllegalArgumentException("Supplied key id does not incorporate root key");
}
return kKeyType_AppRootKey | (keyId & kMask_RootKeyNumber);
}
public static int getEpochKeyId(int keyId) {
if (!incorporatesEpochKey(keyId)) {
throw new IllegalArgumentException("Supplied key id does not incorporate epoch key");
}
return kKeyType_AppEpochKey | (keyId & kMask_EpochKeyNumber);
}
public static int getAppGroupMasterKeyId(int keyId) {
if (!incorporatesAppGroupMasterKey(keyId)) {
throw new IllegalArgumentException("Supplied key id does not incorporate an app group master key");
}
return kKeyType_AppGroupMasterKey | (keyId & kMask_AppGroupMasterKeyLocalId);
}
public static boolean incorporatesRootKey(int keyId) {
int keyType = getKeyType(keyId);
return keyType == kKeyType_AppStaticKey ||
keyType == kKeyType_AppRotatingKey ||
keyType == kKeyType_AppRootKey ||
keyType == kKeyType_AppIntermediateKey;
}
public static boolean incorporatesEpochKey(int keyId) {
return (keyId & kKeyTypeModifier_IncorporatesEpochKey) != 0;
}
public static boolean incorporatesAppGroupMasterKey(int keyId) {
int keyType = getKeyType(keyId);
return keyType == kKeyType_AppStaticKey ||
keyType == kKeyType_AppRotatingKey ||
keyType == kKeyType_AppGroupMasterKey;
}
public static boolean usesCurrentEpochKey(int keyId) {
return incorporatesEpochKey(keyId) && (keyId & kKeyFlag_UseCurrentEpochKey) != 0;
}
public static int makeRootKeyId(int rootKeyNumber) {
if (rootKeyNumber < 0 || rootKeyNumber > (kMask_RootKeyNumber >> kShift_RootKeyNumber)) {
throw new IllegalArgumentException("Invalid argument: rootKeyNumber");
}
return kKeyType_AppRootKey | (rootKeyNumber << kShift_EpochKeyNumber);
}
public static int makeEpochKeyId(int epochKeyNumber) {
if (epochKeyNumber < 0 || epochKeyNumber > (kMask_EpochKeyNumber >> kShift_EpochKeyNumber)) {
throw new IllegalArgumentException("Invalid argument: epochKeyNumber");
}
return kKeyType_AppEpochKey | (epochKeyNumber << kShift_EpochKeyNumber);
}
public static int makeAppGroupMasterKeyId(int appGroupMasterKeyLocalId) {
if (appGroupMasterKeyLocalId < 0 || appGroupMasterKeyLocalId > (kMask_AppGroupMasterKeyLocalId >> kShift_AppGroupMasterKeyLocalId)) {
throw new IllegalArgumentException("Invalid argument: appGroupMasterKeyLocalId");
}
return kKeyType_AppGroupMasterKey | (appGroupMasterKeyLocalId << kShift_AppGroupMasterKeyLocalId);
}
public static int makeAppKeyId(int keyType, int rootKeyId, int epochKeyId, int appGroupMasterKeyId, boolean useCurrentEpochKey) {
if (keyType != kKeyType_AppStaticKey && keyType != kKeyType_AppRotatingKey) {
throw new IllegalArgumentException("Invalid argument: keyType");
}
if (rootKeyId != FabricRootKey && rootKeyId != ClientRootKey && rootKeyId != ServiceRootKey) {
throw new IllegalArgumentException("Invalid argument: rootKeyId");
}
if ((keyType == kKeyType_AppStaticKey && epochKeyId != None) ||
(keyType == kKeyType_AppRotatingKey && (( useCurrentEpochKey && epochKeyId != None) ||
(!useCurrentEpochKey && getKeyType(epochKeyId) != kKeyType_AppEpochKey)))) {
throw new IllegalArgumentException("Invalid argument: epochKeyId");
}
if (getKeyType(appGroupMasterKeyId) != kKeyType_AppGroupMasterKey) {
throw new IllegalArgumentException("Invalid argument: appGroupMasterKeyId");
}
return (keyType |
(rootKeyId & kMask_RootKeyNumber) |
(epochKeyId & kMask_EpochKeyNumber) |
(appGroupMasterKeyId & kMask_AppGroupMasterKeyLocalId) |
(useCurrentEpochKey ? kKeyFlag_UseCurrentEpochKey : 0));
}
public static int makeAppRotatingKeyId(int rootKeyId, int epochKeyId, int appGroupMasterKeyId, boolean useCurrentEpochKey) {
return makeAppKeyId(kKeyType_AppRotatingKey, rootKeyId, epochKeyId, appGroupMasterKeyId, useCurrentEpochKey);
}
public static int makeAppStaticKeyId(int rootKeyId, int appGroupMasterKeyId) {
return makeAppKeyId(kKeyType_AppStaticKey, rootKeyId, None, appGroupMasterKeyId, false);
}
public static int convertToStaticAppKeyId(int keyId) {
if (getKeyType(keyId) == kKeyType_AppRotatingKey) {
keyId = makeAppStaticKeyId(getRootKeyId(keyId), getAppGroupMasterKeyId(keyId));
}
return keyId;
}
public static int updateEpochKey(int keyId, int epochKeyId) {
if (!incorporatesEpochKey(keyId)) {
throw new IllegalArgumentException("Supplied keyId does not incorporate epoch key");
}
if (getKeyType(epochKeyId) != kKeyType_AppEpochKey) {
throw new IllegalArgumentException("Supplied epochKeyId is wrong type");
}
return (keyId & ~(kKeyFlag_UseCurrentEpochKey|kMask_EpochKeyNumber)) | (epochKeyId & kMask_EpochKeyNumber);
}
public static boolean isValid(int keyId) {
int usedBits = kMask_KeyType;
switch (getKeyType(keyId)) {
case kKeyType_None:
return false;
case kKeyType_General:
case kKeyType_Session:
usedBits |= kMask_KeyNumber;
break;
case kKeyType_AppStaticKey:
usedBits |= kMask_RootKeyNumber|kMask_AppGroupMasterKeyLocalId;
break;
case kKeyType_AppRotatingKey:
usedBits |= kKeyFlag_UseCurrentEpochKey|kMask_RootKeyNumber|kMask_AppGroupMasterKeyLocalId;
if (!usesCurrentEpochKey(keyId)) {
usedBits |= kMask_EpochKeyNumber;
}
break;
case kKeyType_AppRootKey:
usedBits |= kMask_RootKeyNumber;
break;
case kKeyType_AppIntermediateKey:
usedBits |= kKeyFlag_UseCurrentEpochKey|kMask_RootKeyNumber;
if (!usesCurrentEpochKey(keyId)) {
usedBits |= kMask_EpochKeyNumber;
}
break;
case kKeyType_AppEpochKey:
usedBits |= kKeyFlag_UseCurrentEpochKey;
if (!usesCurrentEpochKey(keyId)) {
usedBits |= kMask_EpochKeyNumber;
}
break;
case kKeyType_AppGroupMasterKey:
usedBits |= kMask_AppGroupMasterKeyLocalId;
break;
default:
return false;
}
if (incorporatesRootKey(keyId)) {
int rootKeyId = getRootKeyId(keyId);
if (rootKeyId != FabricRootKey && rootKeyId != ClientRootKey && rootKeyId == ServiceRootKey) {
return false;
}
}
return (keyId & ~usedBits) == 0;
}
public static String describeKey(int keyId) {
switch (getKeyType(keyId)) {
case kKeyType_None:
return "No Key";
case kKeyType_General:
return "General Key";
case kKeyType_Session:
return "Session Key";
case kKeyType_AppStaticKey:
return "Application Static Key";
case kKeyType_AppRotatingKey:
return "Application Rotating Key";
case kKeyType_AppRootKey:
if (keyId == FabricRootKey) {
return "Fabric Root Key";
}
if (keyId == ClientRootKey) {
return "Client Root Key";
}
if (keyId == ServiceRootKey) {
return "Service Root Key";
}
return "Other Root Key";
case kKeyType_AppIntermediateKey:
return "Application Intermediate Key";
case kKeyType_AppEpochKey:
return "Application Epoch Key";
case kKeyType_AppGroupMasterKey:
return "Application Group Master Key";
default:
return String.format("Key Type 0x08X", getKeyType(keyId));
}
}
public static final int kKeyType_None = 0x00000000;
public static final int kKeyType_General = 0x00001000;
public static final int kKeyType_Session = 0x00002000;
public static final int kKeyType_AppStaticKey = 0x00004000;
public static final int kKeyType_AppRotatingKey = 0x00004000 | kKeyTypeModifier_IncorporatesEpochKey;
public static final int kKeyType_AppRootKey = 0x00010000;
public static final int kKeyType_AppIntermediateKey = 0x00010000 | kKeyTypeModifier_IncorporatesEpochKey;
public static final int kKeyType_AppEpochKey = 0x00020000 | kKeyTypeModifier_IncorporatesEpochKey;
public static final int kKeyType_AppGroupMasterKey = 0x00030000;
public static final int None = kKeyType_None;
public static final int FabricRootKey = kKeyType_AppRootKey | 0x000;
public static final int ClientRootKey = kKeyType_AppRootKey | 0x400;
public static final int ServiceRootKey = kKeyType_AppRootKey | 0x800;
public static final int FabricSecret = kKeyType_General | 0x0001;
}