/** * @brief Calculate the Endpoint Secondary Signing Key (ESSK) * * @param y2 A pointer to the Y2 term used by all * @param essk A pointer to the output ESSK variable * @param ims_sample_compatibility If true, generate IMS values that are * compatible with the original (incorrect) 100 sample values sent * to Toshiba 2016/01/14. If false, generate the IMS value using * the correct form. */ void calc_essk(uint8_t * y2, mcl_octet * essk, bool ims_sample_compatibility) { uint8_t z2[SHA256_HASH_DIGEST_SIZE]; uint8_t scratch_hash[SHA256_HASH_DIGEST_SIZE]; int status; if (ims_sample_compatibility) { /** * Y2 = sha256(IMS[0:31] xor copy(0x5a, 32)) // (provided) * EPSK[0:31] = sha256(Y2 || copy(0x01, 32)) */ sha256_concat(essk->val, y2, 0x01, 32); } else { /** * Y2 = sha256(IMS[0:31] xor copy(0x5a, 32)) // (provided) * Z2 = sha256(Y2 || copy(0x02, 32)) * ESSK[0:31] = sha256(Z2 || copy(0x01, 32)) */ sha256_concat(z2, y2, 0x02, 32); sha256_concat(scratch_hash, z2, 0x01, 32); memcpy(essk->val, scratch_hash, SHA256_HASH_DIGEST_SIZE); essk->len = SHA256_HASH_DIGEST_SIZE; } essk->len = SHA256_HASH_DIGEST_SIZE; #ifdef IMS_DEBUGMSG display_binary_data(essk->val, essk->len, true, "essk "); #endif }
/** * @brief Calculate the Endpoint Primary Signing Key (EPSK) * * @param y2 A pointer to the Y2 term used by all * @param epsk A pointer to the output EPSK variable */ void calc_epsk(uint8_t * y2, mcl_octet * epsk) { uint8_t z1[SHA256_HASH_DIGEST_SIZE]; uint8_t scratch_hash[SHA256_HASH_DIGEST_SIZE]; int status; /** * Y2 = sha256(IMS[0:31] xor copy(0x5a, 32)) // (provided) * Z1 = sha256(Y2 || copy(0x01, 32)) * EPSK[0:31] = sha256(Z1 || copy(0x01, 32)) * EPSK[32:55] = sha256(Z1 || copy(0x02, 32))[0:23] */ sha256_concat(z1, y2, 0x01, 32); sha256_concat(scratch_hash, z1, 0x01, 32); memcpy(&epsk->val[0], scratch_hash, SHA256_HASH_DIGEST_SIZE); sha256_concat(scratch_hash, z1, 0x02, 32); memcpy(&epsk->val[SHA256_HASH_DIGEST_SIZE], scratch_hash, (EPSK_SIZE - SHA256_HASH_DIGEST_SIZE)); epsk->len = EPSK_SIZE; #ifdef IMS_DEBUGMSG display_binary_data(epsk->val, epsk->len, true, "epsk "); #endif }
static void calculate_ergs(uint8_t *y2, uint8_t *ergs) { uint8_t z5[SHA256_HASH_DIGEST_SIZE]; /* Z5 = sha256(Y2 || copy(0x05, 32)) */ sha256_concat(y2, 0x05, 32, z5); /* ERGS = sha256(Z5 || copy(0x01, 32)) */ sha256_concat(z5, 0x01, 32, ergs); }
static void calculate_epck(uint8_t *y2, uint8_t *epck) { uint8_t z4[SHA256_HASH_DIGEST_SIZE]; /* Z4 = sha256(Y2 || copy(0x04, 32)) */ sha256_concat(y2, 0x04, 32, z4); /* EPCK = sha256(Z4 || copy(0x01, 32)) */ sha256_concat(z4, 0x01, 32, epck); }
static void calculate_essk(uint8_t *y2, uint8_t *essk) { uint8_t z2[SHA256_HASH_DIGEST_SIZE]; /* Z2 = sha256(Y2 || copy(0x02, 32)) */ sha256_concat(y2, 0x02, 32, z2); /* ESSK[0:31] = sha256(Z2 || copy(0x01, 32)) */ sha256_concat(z2, 0x01, 32, essk); }
static void calculate_epsk(uint8_t *y2, uint8_t *epsk) { uint8_t z1[SHA256_HASH_DIGEST_SIZE]; uint8_t t[SHA256_HASH_DIGEST_SIZE]; /* Z1 = sha256(Y2 || copy(0x01, 32)) */ sha256_concat(y2, 0x01, 32, z1); /* EPSK[0:31] = sha256(Z1 || copy(0x01, 32)) */ sha256_concat(z1, 0x01, 32, epsk); /* EPSK[32:51] = sha256(Z1 || copy(0x02, 32))[0:19] */ sha256_concat(z1, 0x02, 32, t); memcpy(&epsk[32], t, 24); }
static void calculate_errk(uint8_t *y2, uint8_t *ims, uint8_t *errk_n) { uint8_t z3[SHA256_HASH_DIGEST_SIZE]; MCL_rsa_public_key_RSA2048 pub; MCL_rsa_private_key_RSA2048 priv; uint8_t errk_p[RSA2048_PUBLIC_KEY_SIZE/2]; uint8_t errk_q[RSA2048_PUBLIC_KEY_SIZE/2]; /* Z3 = sha256(Y2 || copy(0x03, 32)) */ sha256_concat(y2, 0x03, 32, z3); /** * ERRK_P[0:31] = sha256(Z3 || copy(0x01, 32)) * ERRK_P[32:63] = sha256(Z3 || copy(0x02, 32)) * ERRK_P[64:95] = sha256(Z3 || copy(0x03, 32)) * ERRK_P[96:127] = sha256(Z3 || copy(0x04, 32)) * ERRK_P[0] |= 0x03 */ sha256_concat(z3, 0x01, 32, &errk_p[0]); sha256_concat(z3, 0x02, 32, &errk_p[32]); sha256_concat(z3, 0x03, 32, &errk_p[64]); sha256_concat(z3, 0x04, 32, &errk_p[96]); errk_p[0] |= ERRK_ALIAS_MOD_BITS; bytes_to_MCL_FF(errk_p, RSA2048_PUBLIC_KEY_SIZE/2, priv.p, MCL_FFLEN1/2); /** * ERRK_Q[0:31] = sha256(Z3 || copy(0x05, 32)) * ERRK_Q[32:63] = sha256(Z3 || copy(0x06, 32)) * ERRK_Q[64:95] = sha256(Z3 || copy(0x07, 32)) * ERRK_Q[96:127] = sha256(Z3 || copy(0x08, 32)) * ERRK_Q[0] |= 0x03 */ sha256_concat(z3, 0x05, 32, &errk_q[0]); sha256_concat(z3, 0x06, 32, &errk_q[32]); sha256_concat(z3, 0x07, 32, &errk_q[64]); sha256_concat(z3, 0x08, 32, &errk_q[96]); errk_q[0] |= ERRK_ALIAS_MOD_BITS; bytes_to_MCL_FF(errk_q, RSA2048_PUBLIC_KEY_SIZE/2, priv.q, MCL_FFLEN1/2); /* ERRK_P += 4 * IMS[34:32] / 4096 */ /* ERRK_Q += 4 * IMS[34:32] % 4096 */ uint32_t alias_ims = (*((uint32_t *)&ims[32]) & 0x00FFFFFF); MCL_FF_inc_C448(priv.p, (alias_ims >> 12) << ERRK_ALIAS_MOD_SHIFT, MCL_FFLEN1/2); MCL_FF_inc_C448(priv.q, (alias_ims & 0xFFF) << ERRK_ALIAS_MOD_SHIFT, MCL_FFLEN1/2); #if DBG_SECRET_KEY_MSG ff_dump(priv.p, MCL_FFLEN1/2, "p "); ff_dump(priv.q, MCL_FFLEN1/2, "q "); #endif /* ERPK_MOD = ERRK_Q * ERRK_P */ MCL_FF_mul_C448(pub.n, priv.p, priv.q, MCL_FFLEN1/2); #if DBG_SECRET_KEY_MSG ff_dump(pub.n, MCL_FFLEN1, "n "); #endif MCL_FF_to_bytes(pub.n, MCL_FFLEN1, errk_n, RSA2048_PUBLIC_KEY_SIZE); /* ERPK_E = 65537 */ pub.e = 65537; /* TBD: do we even need the private key on the bridge side? */ /* ERRK_D = RSA_secret(ERRK_P, ERRK_Q, ERPK_E) */ }
/** * @brief Calculate the Endpoint Rsa pRivate Key (ERRK) P & Q factors * * Calculates the ERRK_P & ERRK_Q, up to and including the bias-to-odd * step (i.e., that which can be extracted from IMS[0:31]). * * * @param y2 A pointer to the Y2 term used by all * @param ims A pointer to the ims (the upper 3 bytes will be modified) * @param erpk_p A pointer to a buffer to store the ERRK P coefficient * @param errk_q A pointer to a buffer to store the ERPK Q coefficient * @param ims_sample_compatibility If true, generate IMS values that are * compatible with the original (incorrect) 100 sample values sent * to Toshiba 2016/01/14. If false, generate the IMS value using * the correct form. * * @returns Zero if successful, errno otherwise. */ void calc_errk_pq_bias_odd(uint8_t * y2, uint8_t * ims, mcl_octet * errk_p, mcl_octet * errk_q, bool ims_sample_compatibility) { int status = 0; uint8_t z3[SHA256_HASH_DIGEST_SIZE]; uint8_t odd_mod_bitmask; int pq_len; /** * Define constants based on compatibility with the original 100 IMS samples * delivered to Toshiba or the correct production form. */ if (ims_sample_compatibility) { odd_mod_bitmask = ODD_3_MOD_4_BITMASK; pq_len = SHA256_HASH_DIGEST_SIZE; } else { odd_mod_bitmask = ODD_MOD_BITMASK(ODD_MOD_PRODUCTION); pq_len = ERRK_PQ_SIZE; } /** * Y2 = sha256(IMS[0:31] xor copy(0x5a, 32)) // (provided) * Z3 = sha256(Y2 || copy(0x03, 32)) * : */ sha256_concat(z3, y2, 0x03, 32); /** * : * ERRK_P[0:31] = sha256(Z3 || copy(0x01, 32)) * ERRK_P[32:63] = sha256(Z3 || copy(0x02, 32)) * ERRK_P[64:95] = sha256(Z3 || copy(0x03, 32)) * ERRK_P[96:127] = sha256(Z3 || copy(0x41, 32)) * : */ sha256_concat(&errk_p->val[0], z3, 0x01, 32); sha256_concat(&errk_p->val[32], z3, 0x02, 32); sha256_concat(&errk_p->val[64], z3, 0x03, 32); sha256_concat(&errk_p->val[96], z3, 0x04, 32); errk_p->len = pq_len; /** * : * ERRK_Q[0:31] = sha256(Z3 || copy(0x05, 32)) * ERRK_Q[32:63] = sha256(Z3 || copy(0x06, 32)) * ERRK_Q[64:95] = sha256(Z3 || copy(0x07, 32)) * ERRK_Q[96:127] = sha256(Z3 || copy(0x8, 32)) * : */ sha256_concat(&errk_q->val[0], z3, 0x05, 32); sha256_concat(&errk_q->val[32], z3, 0x06, 32); sha256_concat(&errk_q->val[64], z3, 0x07, 32); sha256_concat(&errk_q->val[96], z3, 0x08, 32); errk_q->len = pq_len; /* Force P, Q to be suitably odd */ errk_p->val[0] |= odd_mod_bitmask; errk_q->val[0] |= odd_mod_bitmask; }