+/**\r
+ Performs the PKCS1-v1_5 encoding methods defined in RSA PKCS #1.\r
+\r
+ @param Message Message buffer to be encoded.\r
+ @param MessageSize Size of message buffer in bytes.\r
+ @param DigestInfo Pointer to buffer of digest info for output.\r
+\r
+ @return Size of DigestInfo in bytes.\r
+\r
+**/ \r
+UINTN\r
+DigestInfoEncoding (\r
+ IN CONST UINT8 *Message,\r
+ IN UINTN MessageSize,\r
+ OUT UINT8 *DigestInfo\r
+ )\r
+{\r
+ CONST UINT8 *HashDer;\r
+ UINTN DerSize;\r
+\r
+ ASSERT (Message != NULL);\r
+ ASSERT (DigestInfo != NULL);\r
+\r
+ //\r
+ // The original message length is used to determine the hash algorithm since\r
+ // message is digest value hashed by the specified algorithm.\r
+ //\r
+ switch (MessageSize) {\r
+ case MD5_DIGEST_SIZE:\r
+ HashDer = Asn1IdMd5;\r
+ DerSize = sizeof (Asn1IdMd5);\r
+ break;\r
+ \r
+ case SHA1_DIGEST_SIZE:\r
+ HashDer = Asn1IdSha1;\r
+ DerSize = sizeof (Asn1IdSha1);\r
+ break;\r
+ \r
+ case SHA256_DIGEST_SIZE:\r
+ HashDer = Asn1IdSha256;\r
+ DerSize = sizeof (Asn1IdSha256);\r
+ break;\r
+ \r
+ default:\r
+ return FALSE;\r
+ }\r
+\r
+ CopyMem (DigestInfo, HashDer, DerSize);\r
+ CopyMem (DigestInfo + DerSize, Message, MessageSize);\r
+\r
+ return (DerSize + MessageSize);\r
+}\r
+\r
+/**\r
+ Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.\r
+\r
+ This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in\r
+ RSA PKCS#1.\r
+ If the Signature buffer is too small to hold the contents of signature, FALSE\r
+ is returned and SigSize is set to the required buffer size to obtain the signature.\r
+\r
+ If RsaContext is NULL, then ASSERT().\r
+ If MessageHash is NULL, then ASSERT().\r
+ If HashSize is not equal to the size of MD5, SHA-1 or SHA-256 digest, then ASSERT().\r
+ If SigSize is large enough but Signature is NULL, then ASSERT().\r
+\r
+ @param[in] RsaContext Pointer to RSA context for signature generation.\r
+ @param[in] MessageHash Pointer to octet message hash to be signed.\r
+ @param[in] HashSize Size of the message hash in bytes.\r
+ @param[out] Signature Pointer to buffer to receive RSA PKCS1-v1_5 signature.\r
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.\r
+ On output, the size of data returned in Signature buffer in bytes.\r
+\r
+ @retval TRUE Signature successfully generated in PKCS1-v1_5.\r
+ @retval FALSE Signature generation failed.\r
+ @retval FALSE SigSize is too small.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+RsaPkcs1Sign (\r
+ IN VOID *RsaContext,\r
+ IN CONST UINT8 *MessageHash,\r
+ IN UINTN HashSize,\r
+ OUT UINT8 *Signature,\r
+ IN OUT UINTN *SigSize\r
+ )\r
+{\r
+ RSA *Rsa;\r
+ UINTN Size;\r
+ INTN ReturnVal;\r
+\r
+ ASSERT (RsaContext != NULL);\r
+ ASSERT (MessageHash != NULL);\r
+ ASSERT ((HashSize == MD5_DIGEST_SIZE) ||\r
+ (HashSize == SHA1_DIGEST_SIZE) ||\r
+ (HashSize == SHA256_DIGEST_SIZE));\r
+\r
+ Rsa = (RSA *) RsaContext;\r
+ Size = BN_num_bytes (Rsa->n);\r
+\r
+ if (*SigSize < Size) {\r
+ *SigSize = Size;\r
+ return FALSE;\r
+ }\r
+\r
+ ASSERT (Signature != NULL);\r
+\r
+ Size = DigestInfoEncoding (MessageHash, HashSize, Signature);\r
+\r
+ ReturnVal = RSA_private_encrypt (\r
+ (UINT32) Size,\r
+ Signature,\r
+ Signature,\r
+ Rsa,\r
+ RSA_PKCS1_PADDING\r
+ );\r
+\r
+ if (ReturnVal < (INTN) Size) {\r
+ return FALSE;\r
+ }\r
+\r
+ *SigSize = (UINTN)ReturnVal;\r
+ return TRUE;\r
+}\r