RCM protocol 40 is required for Tegra124 Signed-off-by: Allen Martin <amartin@xxxxxxxxxx> --- src/rcm.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/rcm.h | 58 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 112 insertions(+), 20 deletions(-) diff --git a/src/rcm.c b/src/rcm.c index c5b3aac..cb53d8f 100644 --- a/src/rcm.c +++ b/src/rcm.c @@ -36,6 +36,7 @@ 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 int rcm40_sign_msg(uint8_t *buf); static void rcm_init_msg( uint8_t *buf, uint32_t msg_len, @@ -57,6 +58,13 @@ static void rcm35_init_msg( void *args, uint32_t args_len, uint32_t payload_len); +static void rcm40_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); @@ -79,6 +87,11 @@ int rcm_init(uint32_t version) message_size = sizeof(rcm35_msg_t); ret = 0; } + else if (version == RCM_VERSION_40) { + rcm_version = version; + message_size = sizeof(rcm40_msg_t); + ret = 0; + } return ret; } @@ -88,6 +101,8 @@ uint32_t rcm_get_msg_len(uint8_t *msg) return ((rcm1_msg_t*)msg)->len_insecure; else if (rcm_version == RCM_VERSION_35) return ((rcm35_msg_t*)msg)->len_insecure; + else if (rcm_version == RCM_VERSION_40) + return ((rcm40_msg_t*)msg)->len_insecure; else return 0; } @@ -139,6 +154,8 @@ static int rcm_sign_msg(uint8_t *buf) { if (rcm_version == RCM_VERSION_35) return rcm35_sign_msg(buf); + else if (rcm_version == RCM_VERSION_40) + return rcm40_sign_msg(buf); else if (rcm_version == RCM_VERSION_1) return rcm1_sign_msg(buf); else @@ -184,6 +201,26 @@ static int rcm35_sign_msg(uint8_t *buf) return 0; } +static int rcm40_sign_msg(uint8_t *buf) +{ + rcm40_msg_t *msg; + uint32_t crypto_len; + + msg = (rcm40_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 message_size + payload_len + @@ -215,6 +252,9 @@ static void rcm_init_msg( if (rcm_version == RCM_VERSION_35) rcm35_init_msg(buf, msg_len, opcode, args, args_len, payload_len); + else if (rcm_version == RCM_VERSION_40) + rcm40_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); @@ -254,6 +294,40 @@ static void rcm35_init_msg( rcm_msg_pad(buf + sizeof(rcm35_msg_t) + payload_len, padding_len); } +static void rcm40_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; + rcm40_msg_t *msg; + + msg = (rcm40_msg_t *)buf; + + padding_len = rcm_get_pad_len(payload_len); + + msg->len_insecure = sizeof(rcm40_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_40; + + 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(rcm40_msg_t) + payload_len, padding_len); +} + static void rcm1_init_msg( uint8_t *buf, uint32_t msg_len, diff --git a/src/rcm.h b/src/rcm.h index 1aeca9f..505547c 100644 --- a/src/rcm.h +++ b/src/rcm.h @@ -36,6 +36,7 @@ #define NVBOOT_VERSION(a,b) ((((a)&0xffff) << 16) | ((b)&0xffff)) #define RCM_VERSION_1 (NVBOOT_VERSION(1, 0)) #define RCM_VERSION_35 (NVBOOT_VERSION(0x35, 1)) +#define RCM_VERSION_40 (NVBOOT_VERSION(0x40, 1)) #define RCM_VERSION_MAJOR(ver) ((ver) >> 16) #define RCM_VERSION_MINOR(ver) ((ver) & 0xffff) @@ -58,34 +59,51 @@ * padding */ typedef struct { - uint32_t len_insecure; - uint8_t cmac_hash[RCM_AES_BLOCK_SIZE]; - uint8_t reserved[16]; - uint32_t opcode; - uint32_t len_secure; - uint32_t payload_len; - uint32_t rcm_version; - uint8_t args[48]; - uint8_t padding[16]; + uint32_t len_insecure; // 000-003 + uint8_t cmac_hash[RCM_AES_BLOCK_SIZE]; // 004-013 + uint8_t reserved[16]; // 014-023 + uint32_t opcode; // 024-027 + uint32_t len_secure; // 028-02b + uint32_t payload_len; // 02c-02f + uint32_t rcm_version; // 030-033 + uint8_t args[48]; // 034-063 + uint8_t padding[16]; // 064-073 } rcm1_msg_t; typedef struct { - uint32_t len_insecure; - uint8_t modulus[2048 / 8]; + uint32_t len_insecure; // 000-003 + uint8_t modulus[2048 / 8]; // 004-103 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]; + } object_sig; // 104-203 + uint8_t reserved[16]; // 204-213 + uint32_t ecid[4]; // 214-223 + uint32_t opcode; // 224-227 + uint32_t len_secure; // 228-22b + uint32_t payload_len; // 22c-22f + uint32_t rcm_version; // 230-233 + uint8_t args[48]; // 234-263 + uint8_t padding[16]; // 264-273 } rcm35_msg_t; +typedef struct { + uint32_t len_insecure; // 000-003 + uint8_t modulus[2048 / 8]; // 004-103 + struct { + uint8_t cmac_hash[RCM_AES_BLOCK_SIZE]; + uint8_t rsa_pss_sig[2048 / 8]; + } object_sig; // 104-213 + uint8_t reserved[16]; // 214-223 + uint32_t ecid[4]; // 224-233 + uint32_t opcode; // 234-237 + uint32_t len_secure; // 238-23b + uint32_t payload_len; // 23c-23f + uint32_t rcm_version; // 240-243 + uint8_t args[48]; // 244-273 + uint8_t padding[16]; // 274-283 +} rcm40_msg_t; + // security operating modes #define RCM_OP_MODE_PRE_PRODUCTION 0x1 #define RCM_OP_MODE_DEVEL 0x3 -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html