+/**\r
+ Set the signature algorithm list to used by the TLS object.\r
+\r
+ This function sets the signature algorithms for use by a specified TLS object.\r
+\r
+ @param[in] Tls Pointer to a TLS object.\r
+ @param[in] Data Array of UINT8 of signature algorithms. The array consists of\r
+ pairs of the hash algorithm and the signature algorithm as defined\r
+ in RFC 5246\r
+ @param[in] DataSize The length the SignatureAlgoList. Must be divisible by 2.\r
+\r
+ @retval EFI_SUCCESS The signature algorithm list was set successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+ @retval EFI_UNSUPPORTED No supported TLS signature algorithm was found in SignatureAlgoList\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetSignatureAlgoList (\r
+ IN VOID *Tls,\r
+ IN UINT8 *Data,\r
+ IN UINTN DataSize\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+ UINTN Index;\r
+ UINTN SignAlgoStrSize;\r
+ CHAR8 *SignAlgoStr;\r
+ CHAR8 *Pos;\r
+ UINT8 *SignatureAlgoList;\r
+ EFI_STATUS Status;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize < 3) ||\r
+ ((DataSize % 2) == 0) || (Data[0] != DataSize - 1))\r
+ {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ SignatureAlgoList = Data + 1;\r
+ SignAlgoStrSize = 0;\r
+ for (Index = 0; Index < Data[0]; Index += 2) {\r
+ CONST CHAR8 *Tmp;\r
+\r
+ if (SignatureAlgoList[Index] >= ARRAY_SIZE (TlsHashAlgoToName)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Tmp = TlsHashAlgoToName[SignatureAlgoList[Index]].Name;\r
+ if (!Tmp) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ // Add 1 for the '+'\r
+ SignAlgoStrSize += AsciiStrLen (Tmp) + 1;\r
+\r
+ if (SignatureAlgoList[Index + 1] >= ARRAY_SIZE (TlsSignatureAlgoToName)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Tmp = TlsSignatureAlgoToName[SignatureAlgoList[Index + 1]].Name;\r
+ if (!Tmp) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ // Add 1 for the ':' or for the NULL terminator\r
+ SignAlgoStrSize += AsciiStrLen (Tmp) + 1;\r
+ }\r
+\r
+ if (!SignAlgoStrSize) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ SignAlgoStr = AllocatePool (SignAlgoStrSize);\r
+ if (SignAlgoStr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Pos = SignAlgoStr;\r
+ for (Index = 0; Index < Data[0]; Index += 2) {\r
+ CONST CHAR8 *Tmp;\r
+\r
+ Tmp = TlsHashAlgoToName[SignatureAlgoList[Index]].Name;\r
+ CopyMem (Pos, Tmp, AsciiStrLen (Tmp));\r
+ Pos += AsciiStrLen (Tmp);\r
+ *Pos++ = '+';\r
+\r
+ Tmp = TlsSignatureAlgoToName[SignatureAlgoList[Index + 1]].Name;\r
+ CopyMem (Pos, Tmp, AsciiStrLen (Tmp));\r
+ Pos += AsciiStrLen (Tmp);\r
+ *Pos++ = ':';\r
+ }\r
+\r
+ *(Pos - 1) = '\0';\r
+\r
+ if (SSL_set1_sigalgs_list (TlsConn->Ssl, SignAlgoStr) < 1) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ } else {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ FreePool (SignAlgoStr);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Set the EC curve to be used for TLS flows\r
+\r
+ This function sets the EC curve to be used for TLS flows.\r
+\r
+ @param[in] Tls Pointer to a TLS object.\r
+ @param[in] Data An EC named curve as defined in section 5.1.1 of RFC 4492.\r
+ @param[in] DataSize Size of Data, it should be sizeof (UINT32)\r
+\r
+ @retval EFI_SUCCESS The EC curve was set successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+ @retval EFI_UNSUPPORTED The requested TLS EC curve is not supported\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetEcCurve (\r
+ IN VOID *Tls,\r
+ IN UINT8 *Data,\r
+ IN UINTN DataSize\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+ EC_KEY *EcKey;\r
+ INT32 Nid;\r
+ INT32 Ret;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize != sizeof (UINT32))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ switch (*((UINT32 *)Data)) {\r
+ case TlsEcNamedCurveSecp256r1:\r
+ return EFI_UNSUPPORTED;\r
+ case TlsEcNamedCurveSecp384r1:\r
+ Nid = NID_secp384r1;\r
+ break;\r
+ case TlsEcNamedCurveSecp521r1:\r
+ Nid = NID_secp521r1;\r
+ break;\r
+ case TlsEcNamedCurveX25519:\r
+ Nid = NID_X25519;\r
+ break;\r
+ case TlsEcNamedCurveX448:\r
+ Nid = NID_X448;\r
+ break;\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (SSL_set1_curves (TlsConn->Ssl, &Nid, 1) != 1) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ EcKey = EC_KEY_new_by_curve_name (Nid);\r
+ if (EcKey == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Ret = SSL_set_tmp_ecdh (TlsConn->Ssl, EcKey);\r
+ EC_KEY_free (EcKey);\r
+\r
+ if (Ret != 1) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r