// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2020 NXP * * RSA Signature Software common implementation. * Functions preparing and/or verifying the signature * encoded string. * * PKCS #1 v2.1: RSA Cryptography Standard * https://www.ietf.org/rfc/rfc3447.txt */ #include #include #include #include #include #include #include #include #include #include #include "local.h" /* * PKCS#1 V1.5 - Encode the message in Distinguished Encoding Rules * (DER) format. * Refer to EMSA-PKCS1-v1_5 chapter of the PKCS#1 v2.1 * * @ssa_data RSA data to encode * @EM [out] Encoded Message */ static TEE_Result emsa_pkcs1_v1_5_encode(struct drvcrypt_rsa_ssa *ssa_data, struct drvcrypt_buf *EM) { const struct drvcrypt_oid *hash_oid = NULL; size_t ps_size = 0; uint8_t *buf = NULL; hash_oid = drvcrypt_get_alg_hash_oid(ssa_data->hash_algo); if (!hash_oid) return TEE_ERROR_NOT_SUPPORTED; /* * Calculate the PS size * EM Size (modulus size) - 3 bytes - DigestInfo DER format size */ ps_size = ssa_data->key.n_size - 3; ps_size -= ssa_data->digest_size; ps_size -= 10 + hash_oid->asn1_length; CRYPTO_TRACE("PS size = %zu (n %zu)", ps_size, ssa_data->key.n_size); /* * EM = 0x00 || 0x01 || PS || 0x00 || T * * where T represent the message DigestInfo in DER: * DigestInfo ::= SEQUENCE { * digestAlgorithm AlgorithmIdentifier, * digest OCTET STRING * } * * T Length = digest length + oid length * EM Length = T Length + 11 + PS Length */ buf = EM->data; /* Set the EM first byte to 0x00 */ *buf++ = 0x00; /* Set the EM second byte to 0x01 */ *buf++ = 0x01; /* Fill PS with 0xFF */ memset(buf, UINT8_MAX, ps_size); buf += ps_size; /* Set the Byte after PS to 0x00 */ *buf++ = 0x00; /* * Create the DigestInfo DER Sequence * * DigestInfo ::= SEQUENCE { * digestAlgorithm AlgorithmIdentifier, * digest OCTET STRING * } * */ /* SEQUENCE { */ *buf++ = DRVCRYPT_ASN1_SEQUENCE | DRVCRYPT_ASN1_CONSTRUCTED; *buf++ = 0x08 + hash_oid->asn1_length + ssa_data->digest_size; /* digestAlgorithm AlgorithmIdentifier */ *buf++ = DRVCRYPT_ASN1_SEQUENCE | DRVCRYPT_ASN1_CONSTRUCTED; *buf++ = 0x04 + hash_oid->asn1_length; *buf++ = DRVCRYPT_ASN1_OID; *buf++ = hash_oid->asn1_length; /* digest OCTET STRING */ memcpy(buf, hash_oid->asn1, hash_oid->asn1_length); buf += hash_oid->asn1_length; *buf++ = DRVCRYPT_ASN1_NULL; *buf++ = 0x00; *buf++ = DRVCRYPT_ASN1_OCTET_STRING; *buf++ = ssa_data->digest_size; /* } */ memcpy(buf, ssa_data->message.data, ssa_data->digest_size); CRYPTO_DUMPBUF("Encoded Message", EM->data, (size_t)EM->length); return TEE_SUCCESS; } /* * PKCS#1 V1.5 - Encode the message in Distinguished Encoding Rules * (DER) format. * Refer to EMSA-PKCS1-v1_5 chapter of the PKCS#1 v2.1 * * @ssa_data RSA data to encode * @EM [out] Encoded Message */ static TEE_Result emsa_pkcs1_v1_5_encode_noasn1(struct drvcrypt_rsa_ssa *ssa_data, struct drvcrypt_buf *EM) { size_t ps_size = 0; uint8_t *buf = NULL; /* * Calculate the PS size * EM Size (modulus size) - 3 bytes - Message Length */ ps_size = ssa_data->key.n_size - 3; if (ps_size < ssa_data->message.length) return TEE_ERROR_BAD_PARAMETERS; ps_size -= ssa_data->message.length; CRYPTO_TRACE("PS size = %zu (n %zu)", ps_size, ssa_data->key.n_size); /* * EM = 0x00 || 0x01 || PS || 0x00 || T * * T Length = message length * EM Length = T Length + PS Length */ buf = EM->data; /* Set the EM first byte to 0x00 */ *buf++ = 0x00; /* Set the EM second byte to 0x01 */ *buf++ = 0x01; /* Fill PS with 0xFF */ memset(buf, UINT8_MAX, ps_size); buf += ps_size; /* Set the Byte after PS to 0x00 */ *buf++ = 0x00; memcpy(buf, ssa_data->message.data, ssa_data->message.length); CRYPTO_DUMPBUF("Encoded Message", EM->data, EM->length); return TEE_SUCCESS; } /* * PKCS#1 V1.5 - Signature of RSA message and encodes the signature. * Refer to RSASSA-PKCS1-v1_5 chapter of the PKCS#1 v2.1 * * @ssa_data [in/out] RSA data to sign / Signature */ static TEE_Result rsassa_pkcs1_v1_5_sign(struct drvcrypt_rsa_ssa *ssa_data) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_buf EM = { }; struct drvcrypt_rsa_ed rsa_data = { }; struct drvcrypt_rsa *rsa = NULL; EM.length = ssa_data->key.n_size; EM.data = malloc(EM.length); if (!EM.data) return TEE_ERROR_OUT_OF_MEMORY; /* Encode the Message */ if (ssa_data->algo != TEE_ALG_RSASSA_PKCS1_V1_5) ret = emsa_pkcs1_v1_5_encode(ssa_data, &EM); else ret = emsa_pkcs1_v1_5_encode_noasn1(ssa_data, &EM); if (ret != TEE_SUCCESS) goto out; /* * RSA Encrypt/Decrypt are doing the same operation except * that decrypt takes a RSA Private key in parameter */ rsa_data.key.key = ssa_data->key.key; rsa_data.key.isprivate = true; rsa_data.key.n_size = ssa_data->key.n_size; rsa = drvcrypt_get_ops(CRYPTO_RSA); if (!rsa) { ret = TEE_ERROR_NOT_IMPLEMENTED; goto out; } /* Prepare the decryption data parameters */ rsa_data.rsa_id = DRVCRYPT_RSASSA_PKCS_V1_5; rsa_data.message.data = ssa_data->signature.data; rsa_data.message.length = ssa_data->signature.length; rsa_data.cipher.data = EM.data; rsa_data.cipher.length = EM.length; ret = rsa->decrypt(&rsa_data); /* Set the message decrypted size */ ssa_data->signature.length = rsa_data.message.length; out: free(EM.data); return ret; } /* * PKCS#1 V1.5 - Verification of the RSA message's signature. * Refer to RSASSA-PKCS1-v1_5 chapter of the PKCS#1 v2.1 * * @ssa_data [int/out] RSA data signed and encoded signature */ static TEE_Result rsassa_pkcs1_v1_5_verify(struct drvcrypt_rsa_ssa *ssa_data) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_buf EM = { }; struct drvcrypt_buf EM_gen = { }; struct drvcrypt_rsa_ed rsa_data = { }; struct drvcrypt_rsa *rsa = NULL; EM.length = ssa_data->key.n_size; EM.data = malloc(EM.length); EM_gen.length = ssa_data->key.n_size; EM_gen.data = malloc(EM.length); if (!EM.data || !EM_gen.data) { ret = TEE_ERROR_OUT_OF_MEMORY; goto end_verify; } /* * RSA Encrypt/Decrypt are doing the same operation except * that the encrypt takes a RSA Public key in parameter */ rsa_data.key.key = ssa_data->key.key; rsa_data.key.isprivate = false; rsa_data.key.n_size = ssa_data->key.n_size; rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { /* Prepare the encryption data parameters */ rsa_data.rsa_id = DRVCRYPT_RSASSA_PKCS_V1_5; rsa_data.message.data = ssa_data->signature.data; rsa_data.message.length = ssa_data->signature.length; rsa_data.cipher.data = EM.data; rsa_data.cipher.length = EM.length; ret = rsa->encrypt(&rsa_data); /* Set the cipher size */ EM.length = rsa_data.cipher.length; } else { ret = TEE_ERROR_NOT_IMPLEMENTED; } if (ret != TEE_SUCCESS) goto end_verify; /* Encode the Message */ if (ssa_data->algo != TEE_ALG_RSASSA_PKCS1_V1_5) ret = emsa_pkcs1_v1_5_encode(ssa_data, &EM_gen); else ret = emsa_pkcs1_v1_5_encode_noasn1(ssa_data, &EM_gen); if (ret != TEE_SUCCESS) goto end_verify; /* Check if EM decrypted and EM re-generated are identical */ ret = TEE_ERROR_SIGNATURE_INVALID; if (EM.length == EM_gen.length) { if (!memcmp(EM.data, EM_gen.data, EM.length)) ret = TEE_SUCCESS; } end_verify: free(EM.data); free(EM_gen.data); return ret; } /* * PSS - Encode the message using a Probabilistic Signature Scheme (PSS) * Refer to EMSA-PSS (encoding) chapter of the PKCS#1 v2.1 * * @ssa_data RSA data to encode * @emBits EM size in bits * @EM [out] Encoded Message */ static TEE_Result emsa_pss_encode(struct drvcrypt_rsa_ssa *ssa_data, size_t emBits, struct drvcrypt_buf *EM) { TEE_Result ret = TEE_ERROR_GENERIC; struct drvcrypt_rsa_mgf mgf_data = { }; struct drvcrypt_buf hash = { }; struct drvcrypt_buf dbMask = { }; struct drvcrypt_buf DB = { }; size_t db_size = 0; size_t ps_size = 0; size_t msg_size = 0; uint8_t *buf = NULL; uint8_t *msg_db = NULL; uint8_t *salt = NULL; struct drvcrypt_mod_op mod_op = { }; /* * Build EM = maskedDB || H || 0xbc * * where * maskedDB = DB xor dbMask * DB = PS || 0x01 || salt * dbMask = MGF(H, emLen - hLen - 1) * * H = Hash(M') * M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt * * PS size = emLen - sLen - hLen - 2 (may be = 0) */ /* * Calculate the M' and DB size to allocate a temporary buffer * used for both object */ ps_size = EM->length - ssa_data->digest_size - ssa_data->salt_len - 2; db_size = EM->length - ssa_data->digest_size - 1; msg_size = 8 + ssa_data->digest_size + ssa_data->salt_len; CRYPTO_TRACE("PS Len = %zu, DB Len = %zu, M' Len = %zu", ps_size, db_size, msg_size); msg_db = malloc(MAX(db_size, msg_size)); if (!msg_db) return TEE_ERROR_OUT_OF_MEMORY; if (ssa_data->salt_len) { salt = malloc(ssa_data->salt_len); if (!salt) { ret = TEE_ERROR_OUT_OF_MEMORY; goto end_pss_encode; } } /* * Step 4 and 5 * Generate the M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt * * where * mHash is the input message (already hash) * salt is a random number of salt_len (input data) can be empty */ buf = msg_db; memset(buf, 0, 8); buf += 8; memcpy(buf, ssa_data->message.data, ssa_data->message.length); buf += ssa_data->message.length; /* Get salt random number if salt length not 0 */ if (ssa_data->salt_len) { ret = crypto_rng_read(salt, ssa_data->salt_len); CRYPTO_TRACE("Get salt of %zu bytes (ret = 0x%08" PRIx32 ")", ssa_data->salt_len, ret); if (ret != TEE_SUCCESS) goto end_pss_encode; memcpy(buf, salt, ssa_data->salt_len); } /* * Step 6 * Hash the M' generated new message * H = hash(M') */ hash.data = &EM->data[db_size]; hash.length = ssa_data->digest_size; ret = tee_hash_createdigest(ssa_data->hash_algo, msg_db, msg_size, hash.data, hash.length); CRYPTO_TRACE("H = hash(M') returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto end_pss_encode; CRYPTO_DUMPBUF("H = hash(M')", hash.data, hash.length); /* * Step 7 and 8 * DB = PS || 0x01 || salt */ buf = msg_db; if (ps_size) memset(buf, 0, ps_size); buf += ps_size; *buf++ = 0x01; if (ssa_data->salt_len) memcpy(buf, salt, ssa_data->salt_len); DB.data = msg_db; DB.length = db_size; CRYPTO_DUMPBUF("DB", DB.data, DB.length); /* * Step 9 * Generate a Mask of the seed value * dbMask = MGF(H, emLen - hLen - 1) * * Note: Will use the same buffer for the dbMask and maskedDB * maskedDB is in the EM output */ dbMask.data = EM->data; dbMask.length = db_size; mgf_data.hash_algo = ssa_data->hash_algo; mgf_data.digest_size = ssa_data->digest_size; mgf_data.seed.data = hash.data; mgf_data.seed.length = hash.length; mgf_data.mask.data = dbMask.data; mgf_data.mask.length = dbMask.length; ret = ssa_data->mgf(&mgf_data); CRYPTO_TRACE("dbMask = MGF(H, emLen - hLen - 1) returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto end_pss_encode; CRYPTO_DUMPBUF("dbMask", dbMask.data, dbMask.length); /* * Step 10 * maskedDB = DB xor dbMask */ mod_op.n.length = dbMask.length; mod_op.a.data = DB.data; mod_op.a.length = DB.length; mod_op.b.data = dbMask.data; mod_op.b.length = dbMask.length; mod_op.result.data = dbMask.data; mod_op.result.length = dbMask.length; ret = drvcrypt_xor_mod_n(&mod_op); CRYPTO_TRACE("maskedDB = DB xor dbMask returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto end_pss_encode; CRYPTO_DUMPBUF("maskedDB", dbMask.data, dbMask.length); /* * Step 11 * Set the leftmost 8emLen - emBits of the leftmost octet * in maskedDB to 0' */ EM->data[0] &= (UINT8_MAX >> ((EM->length * 8) - emBits)); /* * Step 12 * EM = maskedDB || H || 0xbc */ EM->data[EM->length - 1] = 0xbc; CRYPTO_DUMPBUF("EM", EM->data, EM->length); ret = TEE_SUCCESS; end_pss_encode: free(msg_db); free(salt); return ret; } /* * PSS - Verify the message using a Probabilistic Signature Scheme (PSS) * Refer to EMSA-PSS (verification) chapter of the PKCS#1 v2.1 * * @ssa_data RSA data to encode * @emBits EM size in bits * @EM [out] Encoded Message */ static TEE_Result emsa_pss_verify(struct drvcrypt_rsa_ssa *ssa_data, size_t emBits, struct drvcrypt_buf *EM) { TEE_Result ret = TEE_ERROR_GENERIC; struct drvcrypt_rsa_mgf mgf_data = { }; struct drvcrypt_buf hash = { }; struct drvcrypt_buf hash_gen = { }; size_t db_size = 0; size_t ps_size = 0; size_t msg_size = 0; uint8_t *msg_db = NULL; uint8_t *salt = NULL; uint8_t *buf = NULL; struct drvcrypt_mod_op mod_op = { }; /* * EM = maskedDB || H || 0xbc * * where * maskedDB = DB xor dbMask * DB = PS || 0x01 || salt * dbMask = MGF(H, emLen - hLen - 1) * * H = Hash(M') * M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt * * PS size = emLen - sLen - hLen - 2 (may be = 0) */ /* * Calculate the M' and DB size to allocate a temporary buffer * used for both object */ ps_size = EM->length - ssa_data->digest_size - ssa_data->salt_len - 2; db_size = EM->length - ssa_data->digest_size - 1; msg_size = 8 + ssa_data->digest_size + ssa_data->salt_len; CRYPTO_TRACE("PS Len = %zu, DB Len = %zu, M' Len = %zu", ps_size, db_size, msg_size); msg_db = malloc(MAX(db_size, msg_size)); if (!msg_db) return TEE_ERROR_OUT_OF_MEMORY; /* * Step 4 * Check if rightmost octet of EM is 0xbc */ if (EM->data[EM->length - 1] != 0xbc) { CRYPTO_TRACE("rigthmost octet != 0xbc (0x%" PRIX8 ")", EM->data[EM->length - 1]); ret = TEE_ERROR_SIGNATURE_INVALID; goto end_pss_verify; } /* * Step 6 * Check if the leftmost 8emLen - emBits of the leftmost octet * in maskedDB are 0's */ if (EM->data[0] & ~(UINT8_MAX >> (EM->length * 8 - emBits))) { CRYPTO_TRACE("Error leftmost octet maskedDB not 0's"); CRYPTO_TRACE("EM[0] = 0x%" PRIX8 " - EM Len = %zu, emBits = %zu", EM->data[0], EM->length, emBits); ret = TEE_ERROR_SIGNATURE_INVALID; goto end_pss_verify; } hash.data = &EM->data[db_size]; hash.length = ssa_data->digest_size; /* * Step 7 * dbMask = MGF(H, emLen - hLen - 1) * * Note: Will use the same buffer for the dbMask and DB */ mgf_data.hash_algo = ssa_data->hash_algo; mgf_data.digest_size = ssa_data->digest_size; mgf_data.seed.data = hash.data; mgf_data.seed.length = hash.length; mgf_data.mask.data = msg_db; mgf_data.mask.length = db_size; ret = ssa_data->mgf(&mgf_data); CRYPTO_TRACE("dbMask = MGF(H, emLen - hLen - 1) returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto end_pss_verify; CRYPTO_DUMPBUF("dbMask", msg_db, db_size); /* * Step 8 * DB = maskedDB xor dbMask * * * Note: maskedDB is in the EM input */ mod_op.n.length = db_size; mod_op.a.data = EM->data; mod_op.a.length = db_size; mod_op.b.data = msg_db; mod_op.b.length = db_size; mod_op.result.data = msg_db; mod_op.result.length = db_size; ret = drvcrypt_xor_mod_n(&mod_op); CRYPTO_TRACE("DB = maskedDB xor dbMask returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto end_pss_verify; /* * Step 9 * Set the leftmost 8emLen - emBits of the leftmost octet in * DB to zero */ *msg_db &= UINT8_MAX >> (EM->length * 8 - emBits); CRYPTO_DUMPBUF("DB", msg_db, db_size); /* * Step 10 * Expected to have * DB = PS || 0x01 || salt * * PS must be 0 * PS size = emLen - sLen - hLen - 2 (may be = 0) */ buf = msg_db; while (buf < msg_db + ps_size) { if (*buf++ != 0) { ret = TEE_ERROR_SIGNATURE_INVALID; goto end_pss_verify; } } if (*buf++ != 0x01) { ret = TEE_ERROR_SIGNATURE_INVALID; goto end_pss_verify; } /* * Step 11 * Get the salt value */ if (ssa_data->salt_len) { salt = malloc(ssa_data->salt_len); if (!salt) { ret = TEE_ERROR_OUT_OF_MEMORY; goto end_pss_verify; } memcpy(salt, buf, ssa_data->salt_len); } /* * Step 12 * Generate the M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt * * where * mHash is the input message (already hash) * salt is a random number of salt_len (input data) can be empty */ buf = msg_db; memset(buf, 0, 8); buf += 8; memcpy(buf, ssa_data->message.data, ssa_data->message.length); buf += ssa_data->message.length; if (ssa_data->salt_len) memcpy(buf, salt, ssa_data->salt_len); /* * Step 13 * Hash the M' generated new message * H' = hash(M') * * Note: reuse the msg_db buffer as Hash result */ hash_gen.data = msg_db; hash_gen.length = ssa_data->digest_size; ret = tee_hash_createdigest(ssa_data->hash_algo, msg_db, msg_size, hash_gen.data, hash_gen.length); CRYPTO_TRACE("H' = hash(M') returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto end_pss_verify; CRYPTO_DUMPBUF("H' = hash(M')", hash_gen.data, hash_gen.length); /* * Step 14 * Compare H and H' */ ret = TEE_ERROR_SIGNATURE_INVALID; if (!memcmp(hash_gen.data, hash.data, hash_gen.length)) ret = TEE_SUCCESS; end_pss_verify: free(msg_db); free(salt); return ret; } /* * PSS - Signature of RSA message and encodes the signature. * Refer to RSASSA-PSS chapter of the PKCS#1 v2.1 * * @ssa_data [in/out] RSA data to sign / Signature */ static TEE_Result rsassa_pss_sign(struct drvcrypt_rsa_ssa *ssa_data) { TEE_Result ret = TEE_ERROR_GENERIC; struct rsa_keypair *key = NULL; struct drvcrypt_buf EM = { }; size_t modBits = 0; struct drvcrypt_rsa_ed rsa_data = { }; struct drvcrypt_rsa *rsa = NULL; key = ssa_data->key.key; /* Get modulus length in bits */ modBits = crypto_bignum_num_bits(key->n); if (modBits <= 0) return TEE_ERROR_BAD_PARAMETERS; /* * EM Length = (modBits - 1) / 8 * if (modBits - 1) is not divisible by 8, one more byte is needed */ modBits--; EM.length = ROUNDUP(modBits, 8) / 8; EM.data = malloc(EM.length); if (!EM.data) return TEE_ERROR_OUT_OF_MEMORY; CRYPTO_TRACE("modBits = %zu, hence EM Length = %zu", modBits + 1, EM.length); /* Encode the Message */ ret = emsa_pss_encode(ssa_data, modBits, &EM); CRYPTO_TRACE("EMSA PSS Encode returned 0x%08" PRIx32, ret); /* * RSA Encrypt/Decrypt are doing the same operation * expect that the decrypt takes a RSA Private key in parameter */ if (ret == TEE_SUCCESS) { rsa_data.key.key = ssa_data->key.key; rsa_data.key.isprivate = true; rsa_data.key.n_size = ssa_data->key.n_size; rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { /* Prepare the decryption data parameters */ rsa_data.rsa_id = DRVCRYPT_RSASSA_PSS; rsa_data.message.data = ssa_data->signature.data; rsa_data.message.length = ssa_data->signature.length; rsa_data.cipher.data = EM.data; rsa_data.cipher.length = EM.length; ret = rsa->decrypt(&rsa_data); /* Set the message decrypted size */ ssa_data->signature.length = rsa_data.message.length; } else { ret = TEE_ERROR_NOT_IMPLEMENTED; } } free(EM.data); return ret; } /* * PSS - Signature verification of RSA message. * Refer to RSASSA-PSS chapter of the PKCS#1 v2.1 * * @ssa_data [in/out] RSA Signature vs. message to verify */ static TEE_Result rsassa_pss_verify(struct drvcrypt_rsa_ssa *ssa_data) { TEE_Result ret = TEE_ERROR_GENERIC; struct rsa_public_key *key = NULL; struct drvcrypt_buf EM = { }; size_t modBits = 0; struct drvcrypt_rsa_ed rsa_data = { }; struct drvcrypt_rsa *rsa = NULL; key = ssa_data->key.key; /* Get modulus length in bits */ modBits = crypto_bignum_num_bits(key->n); if (modBits <= 0) return TEE_ERROR_BAD_PARAMETERS; /* * EM Length = (modBits - 1) / 8 * if (modBits - 1) is not divisible by 8, one more byte is needed */ modBits--; EM.length = ROUNDUP(modBits, 8) / 8; EM.data = malloc(EM.length); if (!EM.data) return TEE_ERROR_OUT_OF_MEMORY; CRYPTO_TRACE("modBits = %zu, hence EM Length = %zu", modBits + 1, EM.length); /* * RSA Encrypt/Decrypt are doing the same operation * expect that the encrypt takes a RSA Public key in parameter */ rsa_data.key.key = ssa_data->key.key; rsa_data.key.isprivate = false; rsa_data.key.n_size = ssa_data->key.n_size; rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { /* Prepare the encryption data parameters */ rsa_data.rsa_id = DRVCRYPT_RSASSA_PSS; rsa_data.message.data = ssa_data->signature.data; rsa_data.message.length = ssa_data->signature.length; rsa_data.cipher.data = EM.data; rsa_data.cipher.length = EM.length; ret = rsa->encrypt(&rsa_data); /* Set the cipher size */ EM.length = rsa_data.cipher.length; } else { ret = TEE_ERROR_NOT_IMPLEMENTED; goto end_pss_verify; } if (ret == TEE_SUCCESS) { /* Verify the Message */ ret = emsa_pss_verify(ssa_data, modBits, &EM); CRYPTO_TRACE("EMSA PSS Verify returned 0x%08" PRIx32, ret); } else { CRYPTO_TRACE("RSA NO PAD returned 0x%08" PRIx32, ret); ret = TEE_ERROR_SIGNATURE_INVALID; } end_pss_verify: free(EM.data); return ret; } TEE_Result drvcrypt_rsassa_sign(struct drvcrypt_rsa_ssa *ssa_data) { switch (ssa_data->algo) { case TEE_ALG_RSASSA_PKCS1_V1_5: case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: return rsassa_pkcs1_v1_5_sign(ssa_data); case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: return rsassa_pss_sign(ssa_data); default: break; } return TEE_ERROR_BAD_PARAMETERS; } TEE_Result drvcrypt_rsassa_verify(struct drvcrypt_rsa_ssa *ssa_data) { switch (ssa_data->algo) { case TEE_ALG_RSASSA_PKCS1_V1_5: case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: return rsassa_pkcs1_v1_5_verify(ssa_data); case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: return rsassa_pss_verify(ssa_data); default: break; } return TEE_ERROR_BAD_PARAMETERS; }