[U-Boot] [PATCH 3/4] rsa: add support of padding pss
Philippe Reynes
philippe.reynes at softathome.com
Tue Oct 2 16:32:39 UTC 2018
We add the support of the padding pss for rsa signature.
This new padding is often recommended instead of pkcs-1.5.
Signed-off-by: Philippe Reynes <philippe.reynes at softathome.com>
---
common/image-sig.c | 4 ++
include/u-boot/rsa.h | 11 ++++
lib/rsa/rsa-sign.c | 8 +++
lib/rsa/rsa-verify.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 196 insertions(+)
diff --git a/common/image-sig.c b/common/image-sig.c
index b7ca657..0aa1f2d 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -76,6 +76,10 @@ struct padding_algo padding_algos[] = {
.name = "pkcs-1.5",
.verify = padding_pkcs_15_verify,
},
+ {
+ .name = "pss",
+ .verify = padding_pss_verify,
+ }
};
struct checksum_algo *image_get_checksum_algo(const char *full_name)
diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h
index 16b4c4c..6193c10 100644
--- a/include/u-boot/rsa.h
+++ b/include/u-boot/rsa.h
@@ -101,6 +101,10 @@ int rsa_verify(struct image_sign_info *info,
int padding_pkcs_15_verify(struct image_sign_info *info,
uint8_t *msg, int msg_len,
const uint8_t *hash, int hash_len);
+
+int padding_pss_verify(struct image_sign_info *info,
+ uint8_t *msg, int msg_len,
+ const uint8_t *hash, int hash_len);
#else
static inline int rsa_verify(struct image_sign_info *info,
const struct image_region region[], int region_count,
@@ -115,6 +119,13 @@ static inline int padding_pkcs_15_verify(struct image_sign_info *info,
{
return -ENXIO;
}
+
+static inline int padding_pss_verify(struct image_sign_info *info,
+ uint8_t *msg, int msg_len,
+ const uint8_t *hash, int hash_len)
+{
+ return -ENXIO;
+}
#endif
#define RSA_DEFAULT_PADDING_NAME "pkcs-1.5"
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
index 6aa0e2a..13c035e 100644
--- a/lib/rsa/rsa-sign.c
+++ b/lib/rsa/rsa-sign.c
@@ -438,6 +438,14 @@ static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo,
goto err_sign;
}
+ if (padding_algo && !strcmp(padding_algo->name, "pss")) {
+ if (EVP_PKEY_CTX_set_rsa_padding(ckey,
+ RSA_PKCS1_PSS_PADDING) <= 0) {
+ ret = rsa_err("Signer padding setup failed");
+ goto err_sign;
+ }
+ }
+
for (i = 0; i < region_count; i++) {
if (!EVP_DigestSignUpdate(context, region[i].data,
region[i].size)) {
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
index 279a9ba..ca5c1fc 100644
--- a/lib/rsa/rsa-verify.c
+++ b/lib/rsa/rsa-verify.c
@@ -80,6 +80,179 @@ int padding_pkcs_15_verify(struct image_sign_info *info,
return 0;
}
+static void u32_i2osp(uint32_t val, uint8_t *buf)
+{
+ buf[0] = (uint8_t)((val >> 24) & 0xff);
+ buf[1] = (uint8_t)((val >> 16) & 0xff);
+ buf[2] = (uint8_t)((val >> 8) & 0xff);
+ buf[3] = (uint8_t)((val >> 0) & 0xff);
+}
+
+int mfg(struct checksum_algo *checksum, uint8_t *seed, int seed_len,
+ uint8_t *output, int output_len)
+{
+ struct image_region region[2];
+ int ret = 0, i, i_output = 0, region_count = 2;
+ uint32_t counter = 0;
+ uint8_t buf_counter[4], *tmp;
+ int hash_len = checksum->checksum_len;
+
+ memset(output, 0, output_len);
+
+ region[0].data = seed;
+ region[0].size = seed_len;
+ region[1].data = &buf_counter[0];
+ region[1].size = 4;
+
+ tmp = malloc(hash_len);
+ if (!tmp) {
+ debug("%s: can't allocate array tmp\n", __func__);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ while (i_output < output_len) {
+ u32_i2osp(counter, &buf_counter[0]);
+
+ ret = checksum->calculate(checksum->name,
+ region, region_count,
+ tmp);
+ if (ret < 0) {
+ debug("%s: Error in checksum calculation\n", __func__);
+ goto out;
+ }
+
+ i = 0;
+ while ((i_output < output_len) && (i < hash_len)) {
+ output[i_output] = tmp[i];
+ i_output++;
+ i++;
+ }
+
+ counter++;
+ }
+
+out:
+ free(tmp);
+ return ret;
+}
+
+int compute_hash_prime(struct checksum_algo *checksum,
+ uint8_t *pad, int pad_len,
+ uint8_t *hash, int hash_len,
+ uint8_t *salt, int salt_len,
+ uint8_t *hprime)
+{
+ struct image_region region[3];
+ int ret, region_count = 3;
+
+ region[0].data = pad;
+ region[0].size = pad_len;
+ region[1].data = hash;
+ region[1].size = hash_len;
+ region[2].data = salt;
+ region[2].size = salt_len;
+
+ ret = checksum->calculate(checksum->name, region, region_count, hprime);
+ if (ret < 0) {
+ debug("%s: Error in checksum calculation\n", __func__);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+int padding_pss_verify(struct image_sign_info *info,
+ uint8_t *msg, int msg_len,
+ const uint8_t *hash, int hash_len)
+{
+ uint8_t *masked_db = NULL;
+ int masked_db_len = msg_len - hash_len - 1;
+ uint8_t *h = NULL, *hprime = NULL;
+ int h_len = hash_len;
+ uint8_t *db_mask = NULL;
+ int db_mask_len = masked_db_len;
+ uint8_t *db = NULL, *salt = NULL;
+ int db_len = masked_db_len, salt_len = msg_len - hash_len - 2;
+ uint8_t pad_zero[8] = { 0 };
+ int ret, i, leftmost_bits = 1;
+ uint8_t leftmost_mask;
+ struct checksum_algo *checksum = info->checksum;
+
+ /* first, allocate everything */
+ masked_db = malloc(masked_db_len);
+ h = malloc(h_len);
+ db_mask = malloc(db_mask_len);
+ db = malloc(db_len);
+ salt = malloc(salt_len);
+ hprime = malloc(hash_len);
+ if (!masked_db || !h || !db_mask || !db || !salt || !hprime) {
+ printf("%s: can't allocate some buffer\n", __func__);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* step 4: check if the last byte is 0xbc */
+ if (msg[msg_len - 1] != 0xbc) {
+ printf("%s: invalid pss padding (0xbc is missing)\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* step 5 */
+ memcpy(masked_db, msg, masked_db_len);
+ memcpy(h, msg + masked_db_len, h_len);
+
+ /* step 6 */
+ leftmost_mask = (0xff >> (8 - leftmost_bits)) << (8 - leftmost_bits);
+ if (masked_db[0] & leftmost_mask) {
+ printf("%s: invalid pss padding ", __func__);
+ printf("(leftmost bit of maskedDB not zero)\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* step 7 */
+ mfg(checksum, h, h_len, db_mask, db_mask_len);
+
+ /* step 8 */
+ for (i = 0; i < db_len; i++)
+ db[i] = masked_db[i] ^ db_mask[i];
+
+ /* step 9 */
+ db[0] &= 0xff >> leftmost_bits;
+
+ /* step 10 */
+ if (db[0] != 0x01) {
+ printf("%s: invalid pss padding ", __func__);
+ printf("(leftmost byte of db isn't 0x01)\n");
+ ret = EINVAL;
+ goto out;
+ }
+
+ /* step 11 */
+ memcpy(salt, &db[1], salt_len);
+
+ /* step 12 & 13 */
+ compute_hash_prime(checksum, pad_zero, 8,
+ (uint8_t *)hash, hash_len,
+ salt, salt_len, hprime);
+
+ /* step 14 */
+ ret = memcmp(h, hprime, hash_len);
+
+out:
+ free(hprime);
+ free(salt);
+ free(db);
+ free(db_mask);
+ free(h);
+ free(masked_db);
+
+ return ret;
+}
+
/**
* rsa_verify_key() - Verify a signature against some data using RSA Key
*
--
2.7.4
More information about the U-Boot
mailing list