+\r
+/**\r
+ Retrieve the TBSCertificate from one given X.509 certificate.\r
+\r
+ @param[in] Cert Pointer to the given DER-encoded X509 certificate.\r
+ @param[in] CertSize Size of the X509 certificate in bytes.\r
+ @param[out] TBSCert DER-Encoded To-Be-Signed certificate.\r
+ @param[out] TBSCertSize Size of the TBS certificate in bytes.\r
+\r
+ If Cert is NULL, then return FALSE.\r
+ If TBSCert is NULL, then return FALSE.\r
+ If TBSCertSize is NULL, then return FALSE.\r
+\r
+ @retval TRUE The TBSCertificate was retrieved successfully.\r
+ @retval FALSE Invalid X.509 certificate.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+X509GetTBSCert (\r
+ IN CONST UINT8 *Cert,\r
+ IN UINTN CertSize,\r
+ OUT UINT8 **TBSCert,\r
+ OUT UINTN *TBSCertSize\r
+ )\r
+{\r
+ CONST UINT8 *Temp;\r
+ INTN Asn1Tag;\r
+ INTN ObjClass;\r
+ UINTN Length;\r
+\r
+ //\r
+ // Check input parameters.\r
+ //\r
+ if ((Cert == NULL) || (TBSCert == NULL) || (TBSCertSize == NULL)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // An X.509 Certificate is: (defined in RFC3280)\r
+ // Certificate ::= SEQUENCE {\r
+ // tbsCertificate TBSCertificate,\r
+ // signatureAlgorithm AlgorithmIdentifier,\r
+ // signature BIT STRING }\r
+ //\r
+ // and\r
+ //\r
+ // TBSCertificate ::= SEQUENCE {\r
+ // version [0] Version DEFAULT v1,\r
+ // ...\r
+ // }\r
+ //\r
+ // So we can just ASN1-parse the x.509 DER-encoded data. If we strip\r
+ // the first SEQUENCE, the second SEQUENCE is the TBSCertificate.\r
+ //\r
+ Temp = Cert;\r
+ ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)CertSize);\r
+\r
+ if (Asn1Tag != V_ASN1_SEQUENCE) {\r
+ return FALSE;\r
+ }\r
+\r
+ *TBSCert = (UINT8 *)Temp;\r
+\r
+ ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)Length);\r
+ //\r
+ // Verify the parsed TBSCertificate is one correct SEQUENCE data.\r
+ //\r
+ if (Asn1Tag != V_ASN1_SEQUENCE) {\r
+ return FALSE;\r
+ }\r
+\r
+ *TBSCertSize = Length + (Temp - *TBSCert);\r
+ \r
+ return TRUE;\r
+}\r