Skip to content

Commit

Permalink
Implementing Functions for BYOK Interfaces
Browse files Browse the repository at this point in the history
1. complete BYOK interface
2. generate timestamp for BYOK token and verify the input token
3. add new task to remove the expired session every 24h

Signed-off-by: lisiteng <[email protected]>
  • Loading branch information
lisiteng authored and syan10 committed Feb 27, 2024
1 parent 3c25d58 commit e050afa
Show file tree
Hide file tree
Showing 6 changed files with 272 additions and 18 deletions.
5 changes: 4 additions & 1 deletion ehsm_kms_service/apis.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ const cryptographic = {
AsymmetricEncrypt: 'AsymmetricEncrypt',
AsymmetricDecrypt: 'AsymmetricDecrypt',
ExportDataKey: 'ExportDataKey',
GetPublicKey: 'GetPublicKey'
GetPublicKey: 'GetPublicKey',
ImportKeyMaterial: 'ImportKeyMaterial',
GetParametersForImport: 'GetParametersForImport'
}

const enroll = {
Expand Down Expand Up @@ -46,6 +48,7 @@ const secret_manager = {
const common = {
GetVersion: 'GetVersion',
GenHmac: 'GenHmac',
GenTokenHmac: 'GenTokenHmac',
}

const KMS_ACTION = {
Expand Down
10 changes: 7 additions & 3 deletions ehsm_kms_service/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ const Definition = {
SM_SECRET_VERSION_STAGE_CURRENT: 1,
SM_SECRET_VERSION_STAGE_PREVIOUS: 0,
DEFAULT_DELETE_RECOVERY_DAYS: 30,
MAX_NONCE_LEN: 64,
FFI_BUFFER_SIZE: 10000
MAX_NONCE_LEN: 64,
FFI_BUFFER_SIZE: 10000,
TOKEN_LOOP_CLEAR_TIME: 12 * 60 * 60 * 1000,
IMPORT_TOKEN_EFFECTIVE_DURATION: 24 * 60 * 60 * 1000
}

const ehsm_keySpec_t = {
Expand Down Expand Up @@ -83,7 +85,9 @@ const ehsm_action_t = {
[KMS_ACTION.remote_attestation.GenerateQuote]: 15,
[KMS_ACTION.remote_attestation.VerifyQuote]: 16,
[KMS_ACTION.common.GenHmac]: 17,

[KMS_ACTION.common.GenTokenHmac]: 18,
[KMS_ACTION.cryptographic.ImportKeyMaterial]: 19,
[KMS_ACTION.cryptographic.GetParametersForImport]: 20,
}

const kms_config = {
Expand Down
6 changes: 6 additions & 0 deletions ehsm_kms_service/ehsm_kms_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const {
_cmk_cache_timer,
base64_decode,
base64_encode,
_token_time_verify,
_result
} = require('./function')
const connectDB = require('./couchdb')
Expand Down Expand Up @@ -63,6 +64,11 @@ const server = (DB) => {
*/
const { timer: nonce_cache_timer, nonce_database } = _nonce_cache_timer()

/**
* Check token expiration time every twelve hours.
*/
_token_time_verify(DB)

/**
* Clear expired cmks
*/
Expand Down
123 changes: 117 additions & 6 deletions ehsm_kms_service/function.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,60 @@ const _nonce_cache_timer = () => {
}
}

/**
* Clear keyblobs with token time more than 24 hours.
*/
const _token_time_verify = (DB) => {
setInterval(() => {
try {
const current_time = new Date()
.getTime()
const query = {
selector: {
//Query criteria
token_expired_time: {
$lt: current_time
},
},
fields: ['_id',
'_rev',
'keyid',
'keyBlob',
'creator',
'creationDate',
'expireTime',
'alias',
'keyspec',
'origin',
'keyState',
'sessionkeyBlob',
'token_expired_time'
], // Fields returned after query
limit: 10000,
}
DB.partitionedFind('cmk', query) // Query expired cmks
.then((cmks_res) => {
if (cmks_res.docs.length > 0) {
for (const cmk_item of cmks_res.docs) {
cmk_item.keyBlob = ''
}
DB.bulk({
docs: cmks_res.docs
}) // Batch delete expired cmks
.catch((err) => {
logger.error(err)
})
}
})
.catch((err) => {
logger.error(err)
})
} catch (err) {
logger.error(err)
}
}, Definition.TOKEN_LOOP_CLEAR_TIME)
}

/**
* CMK is valid for 5 years and 10 days
* Clean up CMK overdue for more than ten days at three o'clock every day .
Expand Down Expand Up @@ -162,8 +216,7 @@ function store_cmk(napi_res, res, appid, payload, DB) {
origin,
keyusage
} = payload

DB.insert({
const cmkData = {
_id: `cmk:${keyid}`,
keyid,
keyBlob: napi_res.result.cmk,
Expand All @@ -175,7 +228,13 @@ function store_cmk(napi_res, res, appid, payload, DB) {
origin,
keyusage,
keyState: 1,
})
}

if (origin === ehsm_keyorigin_t.EH_EXTERNAL_KEY) {
cmkData.sessionkeyBlob = ''
}

DB.insert(cmkData)
.then((r) => {
delete napi_res.result.cmk // Delete cmk in NaPi result
napi_res.result.keyid = keyid // The keyID field is added to the result returned to the user
Expand Down Expand Up @@ -337,7 +396,7 @@ const enroll_user_info = (action, DB, res, req) => {
logger.error('database is unavailable')
res.send(_result(500, 'enroll user info failed', e))
})
}else {
} else {
logger.error('encrypt apikey failed')
res.send(_result(500, 'enroll user info failed'))
}
Expand Down Expand Up @@ -461,12 +520,12 @@ const _checkParams = function (req, res, next, nonce_database, DB) {
res.send(_result(400, 'param type error'))
return
}
if (nonce != null && nonce != undefined){
if (nonce != null && nonce != undefined) {
if (nonce.length > Definition.MAX_NONCE_LEN) {
res.send(_result(400, 'Nonce length error'))
return
}
}
}
if (timestamp.length != Definition.TIMESTAMP_LEN) {
res.send(_result(400, 'Timestamp length error'))
return
Expand Down Expand Up @@ -664,6 +723,55 @@ const gen_hmac = async (DB, appid, sign_params) => {
}
}

/**
* Gen Token Hmac of importToken.
* @param {string} sessionkey
* @param {object} importToken
* @returns {object} (error, hmac) // One object contain "error" and "hmac" attributes
*/
const gen_token_hmac = async (sessionkey, importToken) => {
try {
const { result } = napi_result(
KMS_ACTION.common.GenTokenHmac,
undefined,
{
sessionkey,
importToken,
})
return {
error: '',
hmac: result.hmac,
}

} catch (error) {
logger.error(error)
return {
error: error,
hmac: ''
}
}
}

/**
* Compare string size on const time.
* @param {string} str1
* @param {string} str2
* @returns true | false
*/
function consttime_equal_compare(str1, str2) {
let result = 0
if (str1 == undefined || str2 == undefined) {
return true;
}
if (str1.length !== str2.length) {
return false;
}
for (let i = 0; i < str1.length; i++) {
result |= str1[i] ^ str2[i];
}
return !result;
}

module.exports = {
getIPAdress,
base64_encode,
Expand All @@ -677,4 +785,7 @@ module.exports = {
store_cmk,
_cmk_cache_timer,
gen_hmac,
gen_token_hmac,
_token_time_verify,
consttime_equal_compare,
}
18 changes: 18 additions & 0 deletions ehsm_kms_service/payload_checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,24 @@ const cryptographic_params = {
[KMS_ACTION.cryptographic.GetPublicKey]: {
keyid,
},
[KMS_ACTION.cryptographic.GetParametersForImport]: {
keyid,
keyspec: {
type: PARAM_DATA_TYPE.CONST,
arr: Object.keys(ehsm_keySpec_t),
required: true,
},
},
[KMS_ACTION.cryptographic.ImportKeyMaterial]: {
keyid,
padding_mode,
key_material: {
type: PARAM_DATA_TYPE.BASE64,
maxLength: MAX_LENGTH * 4 / 3, // This is the length after base64 encoding.
minLength: 1,
required: true,
},
},
[KMS_ACTION.cryptographic.AsymmetricDecrypt]: {
keyid,
ciphertext: {
Expand Down
Loading

0 comments on commit e050afa

Please sign in to comment.