summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllen Martin <amartin@nvidia.com>2012-11-19 17:01:46 -0800
committerAllen Martin <amartin@nvidia.com>2012-11-29 23:26:26 -0800
commit44ecb33b46f3b2bf39fdda8923111975cce6ab62 (patch)
tree26bf09baf673138acfe6499fb8e5d9dbd38050a0
parent5e9196a0e3a6aa95efd93a74625227656052f078 (diff)
downloadtegrarcm-44ecb33b46f3b2bf39fdda8923111975cce6ab62.tar.gz
Add support for RCM protocol version 35
T114 uses version 35 of RCM protocol, in preparation for adding T114 support to tegrarcm add support for this version of RCM protocol. The message size has changed because new fields were added and the version number was bumped to 0x35. None of the new fields are actually used by tegrarcm, so the only changes are to handle the size and version differences. Signed-off-by: Allen Martin <amartin@nvidia.com> Change-Id: I2ff66205e5f1a9f2efbee711f7bad784ae297edf Reviewed-on: http://git-master/r/164850 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Stephen Warren <swarren@nvidia.com>
-rw-r--r--src/main.c5
-rw-r--r--src/rcm.c145
-rw-r--r--src/rcm.h23
3 files changed, 159 insertions, 14 deletions
diff --git a/src/main.c b/src/main.c
index 89f04c9..ebc766e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -182,6 +182,11 @@ int main(int argc, char **argv)
printf("uid: 0x%" PRIx64 "\n", uid);
+ // initialize RCM
+ ret = rcm_init(RCM_VERSION_1);
+ if (ret)
+ error(1, errno, "RCM initialize failed");
+
// create query version message
rcm_create_msg(RCM_CMD_QUERY_RCM_VERSION, NULL, 0, NULL, 0, &msg_buff);
diff --git a/src/rcm.c b/src/rcm.c
index 2fed49f..c5b3aac 100644
--- a/src/rcm.c
+++ b/src/rcm.c
@@ -34,6 +34,8 @@
#include "aes-cmac.h"
static int rcm_sign_msg(uint8_t *buf);
+static int rcm1_sign_msg(uint8_t *buf);
+static int rcm35_sign_msg(uint8_t *buf);
static void rcm_init_msg(
uint8_t *buf,
uint32_t msg_len,
@@ -41,14 +43,53 @@ static void rcm_init_msg(
void *args,
uint32_t args_len,
uint32_t payload_len);
+static void rcm1_init_msg(
+ uint8_t *buf,
+ uint32_t msg_len,
+ uint32_t opcode,
+ void *args,
+ uint32_t args_len,
+ uint32_t payload_len);
+static void rcm35_init_msg(
+ uint8_t *buf,
+ uint32_t msg_len,
+ uint32_t opcode,
+ void *args,
+ uint32_t args_len,
+ uint32_t payload_len);
static uint8_t *rcm_get_msg_payload(uint8_t *buf);
static void rcm_msg_pad(uint8_t *data, uint32_t len);
static uint32_t rcm_get_pad_len(uint32_t payload_len);
static uint32_t rcm_get_msg_buf_len(uint32_t payload_len);
+static uint32_t rcm_version = 0;
+static uint32_t message_size = 0;
+
+int rcm_init(uint32_t version)
+{
+ int ret = -EINVAL;
+
+ if (version == RCM_VERSION_1) {
+ rcm_version = version;
+ message_size = sizeof(rcm1_msg_t);
+ ret = 0;
+ }
+ else if (version == RCM_VERSION_35) {
+ rcm_version = version;
+ message_size = sizeof(rcm35_msg_t);
+ ret = 0;
+ }
+ return ret;
+}
+
uint32_t rcm_get_msg_len(uint8_t *msg)
{
- return ((rcm_msg_t*)msg)->len_insecure;
+ if (rcm_version == RCM_VERSION_1)
+ return ((rcm1_msg_t*)msg)->len_insecure;
+ else if (rcm_version == RCM_VERSION_35)
+ return ((rcm35_msg_t*)msg)->len_insecure;
+ else
+ return 0;
}
int rcm_create_msg(
@@ -96,10 +137,20 @@ done:
static int rcm_sign_msg(uint8_t *buf)
{
- rcm_msg_t *msg;
+ if (rcm_version == RCM_VERSION_35)
+ return rcm35_sign_msg(buf);
+ else if (rcm_version == RCM_VERSION_1)
+ return rcm1_sign_msg(buf);
+ else
+ return -EINVAL;
+}
+
+static int rcm1_sign_msg(uint8_t *buf)
+{
+ rcm1_msg_t *msg;
uint32_t crypto_len;
- msg = (rcm_msg_t*)buf;
+ msg = (rcm1_msg_t*)buf;
// signing does not include the len_insecure and
// cmac_hash fields at the beginning of the message.
@@ -113,15 +164,35 @@ static int rcm_sign_msg(uint8_t *buf)
return 0;
}
+static int rcm35_sign_msg(uint8_t *buf)
+{
+ rcm35_msg_t *msg;
+ uint32_t crypto_len;
+
+ msg = (rcm35_msg_t*)buf;
+
+ // signing does not include the len_insecure, modulus
+ // and object signature at the beginning of the message
+ crypto_len = msg->len_insecure - sizeof(msg->len_insecure) -
+ sizeof(msg->modulus) -
+ sizeof(msg->object_sig);
+ if (crypto_len % RCM_AES_BLOCK_SIZE) {
+ return -EMSGSIZE;
+ }
+
+ cmac_hash(msg->reserved, crypto_len, msg->object_sig.cmac_hash);
+ return 0;
+}
+
static uint32_t rcm_get_msg_buf_len(uint32_t payload_len)
{
- return sizeof(rcm_msg_t) + payload_len +
+ return message_size + payload_len +
rcm_get_pad_len(payload_len);
}
static uint8_t *rcm_get_msg_payload(uint8_t *buf)
{
- return buf + sizeof(rcm_msg_t);
+ return buf + message_size;
}
static void rcm_msg_pad(uint8_t *data, uint32_t len)
@@ -141,14 +212,64 @@ static void rcm_init_msg(
uint32_t args_len,
uint32_t payload_len)
{
+ if (rcm_version == RCM_VERSION_35)
+ rcm35_init_msg(buf, msg_len, opcode, args,
+ args_len, payload_len);
+ else if (rcm_version == RCM_VERSION_1)
+ rcm1_init_msg(buf, msg_len, opcode, args,
+ args_len, payload_len);
+}
+
+static void rcm35_init_msg(
+ uint8_t *buf,
+ uint32_t msg_len,
+ uint32_t opcode,
+ void *args,
+ uint32_t args_len,
+ uint32_t payload_len)
+{
+ uint32_t padding_len;
+ rcm35_msg_t *msg;
+
+ msg = (rcm35_msg_t *)buf;
+
+ padding_len = rcm_get_pad_len(payload_len);
+
+ msg->len_insecure = sizeof(rcm35_msg_t) + payload_len +
+ padding_len;
+
+ memset(&msg->object_sig.cmac_hash, 0x0, sizeof(msg->object_sig.cmac_hash));
+ memset(&msg->reserved, 0x0, sizeof(msg->reserved));
+
+ msg->opcode = opcode;
+ msg->len_secure = msg->len_insecure;
+ msg->payload_len = payload_len;
+ msg->rcm_version = RCM_VERSION_35;
+
+ if (args_len)
+ memcpy(msg->args, args, args_len);
+ memset(msg->args + args_len, 0x0, sizeof(msg->args) - args_len);
+
+ rcm_msg_pad(msg->padding, sizeof(msg->padding));
+ rcm_msg_pad(buf + sizeof(rcm35_msg_t) + payload_len, padding_len);
+}
+
+static void rcm1_init_msg(
+ uint8_t *buf,
+ uint32_t msg_len,
+ uint32_t opcode,
+ void *args,
+ uint32_t args_len,
+ uint32_t payload_len)
+{
uint32_t padding_len;
- rcm_msg_t *msg;
+ rcm1_msg_t *msg;
- msg = (rcm_msg_t *)buf;
+ msg = (rcm1_msg_t *)buf;
padding_len = rcm_get_pad_len(payload_len);
- msg->len_insecure = sizeof(rcm_msg_t) + payload_len +
+ msg->len_insecure = sizeof(rcm1_msg_t) + payload_len +
padding_len;
memset(&msg->cmac_hash, 0x0, sizeof(msg->cmac_hash));
@@ -157,20 +278,20 @@ static void rcm_init_msg(
msg->opcode = opcode;
msg->len_secure = msg->len_insecure;
msg->payload_len = payload_len;
- msg->rcm_version = RCM_VERSION;
+ msg->rcm_version = RCM_VERSION_1;
if (args_len)
memcpy(msg->args, args, args_len);
memset(msg->args + args_len, 0x0, sizeof(msg->args) - args_len);
rcm_msg_pad(msg->padding, sizeof(msg->padding));
- rcm_msg_pad(buf + sizeof(rcm_msg_t) + payload_len, padding_len);
+ rcm_msg_pad(buf + sizeof(rcm1_msg_t) + payload_len, padding_len);
}
static uint32_t rcm_get_pad_len(uint32_t payload_len)
{
uint32_t pad_len = 0;
- uint32_t msg_len = sizeof(rcm_msg_t) + payload_len;
+ uint32_t msg_len = message_size + payload_len;
// First, use padding to bump the message size up to the minimum.
if (msg_len < RCM_MIN_MSG_LENGTH) {
@@ -184,7 +305,7 @@ static uint32_t rcm_get_pad_len(uint32_t payload_len)
* rcm_msg_t size handles the initial data that is not part of
* the hashing and encryption.
*/
- pad_len += 16 - ((msg_len - sizeof(rcm_msg_t)) & 0xf);
+ pad_len += 16 - ((msg_len - message_size) & 0xf);
return pad_len;
}
diff --git a/src/rcm.h b/src/rcm.h
index 868893e..1aeca9f 100644
--- a/src/rcm.h
+++ b/src/rcm.h
@@ -34,7 +34,8 @@
#define RCM_MIN_MSG_LENGTH 1024 // In bytes
#define NVBOOT_VERSION(a,b) ((((a)&0xffff) << 16) | ((b)&0xffff))
-#define RCM_VERSION (NVBOOT_VERSION(1, 0))
+#define RCM_VERSION_1 (NVBOOT_VERSION(1, 0))
+#define RCM_VERSION_35 (NVBOOT_VERSION(0x35, 1))
#define RCM_VERSION_MAJOR(ver) ((ver) >> 16)
#define RCM_VERSION_MINOR(ver) ((ver) & 0xffff)
@@ -66,13 +67,31 @@ typedef struct {
uint32_t rcm_version;
uint8_t args[48];
uint8_t padding[16];
-} rcm_msg_t;
+} rcm1_msg_t;
+
+typedef struct {
+ uint32_t len_insecure;
+ uint8_t modulus[2048 / 8];
+ union {
+ uint8_t cmac_hash[RCM_AES_BLOCK_SIZE];
+ uint8_t rsa_pss_sig[2048 / 8];
+ } object_sig;
+ uint8_t reserved[16];
+ uint32_t ecid[4];
+ uint32_t opcode;
+ uint32_t len_secure;
+ uint32_t payload_len;
+ uint32_t rcm_version;
+ uint8_t args[48];
+ uint8_t padding[16];
+} rcm35_msg_t;
// security operating modes
#define RCM_OP_MODE_PRE_PRODUCTION 0x1
#define RCM_OP_MODE_DEVEL 0x3
#define RCM_OP_MODE_ODM_OPEN 0x5
+int rcm_init(uint32_t version);
uint32_t rcm_get_msg_len(uint8_t *msg);
int rcm_create_msg(
uint32_t opcode,