diff options
| author | Gary Lin <glin@suse.com> | 2015-12-15 10:48:10 +0800 |
|---|---|---|
| committer | Peter Jones <pjones@redhat.com> | 2016-09-06 15:05:34 -0400 |
| commit | e571428e21280c28d0d591b70f13add7d8dbfe81 (patch) | |
| tree | fadafcf006016eb83dd989969d2232048048bad8 /Cryptlib/Pk/CryptPkcs7Verify.c | |
| parent | 7052e75307553edc8f04eb529b0d37844fbcc30b (diff) | |
| download | efi-boot-shim-e571428e21280c28d0d591b70f13add7d8dbfe81.tar.gz efi-boot-shim-e571428e21280c28d0d591b70f13add7d8dbfe81.zip | |
Update to openssl to 1.0.2e
Also update Cryptlib to edk2 r19218
- Undefine NO_BUILTIN_VA_FUNCS in Cryptlib/OpenSSL/ for x86_64 to use
the gcc builtins and remove all EFIAPI from the functions
- Move the most of defines into the headers instead of Makefile
- Remove the global variable 'timeval'
- Remove the unused code: crypto/pqueue/* and crypto/ts/*
- Include bn.h in MokManager.c due to the changes in openssl
Signed-off-by: Gary Lin <glin@suse.com>
Diffstat (limited to 'Cryptlib/Pk/CryptPkcs7Verify.c')
| -rw-r--r-- | Cryptlib/Pk/CryptPkcs7Verify.c | 382 |
1 files changed, 295 insertions, 87 deletions
diff --git a/Cryptlib/Pk/CryptPkcs7Verify.c b/Cryptlib/Pk/CryptPkcs7Verify.c index d0b0c838..559610d7 100644 --- a/Cryptlib/Pk/CryptPkcs7Verify.c +++ b/Cryptlib/Pk/CryptPkcs7Verify.c @@ -31,87 +31,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. UINT8 mOidValue[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 };
/**
- Verification callback function to override any existing callbacks in OpenSSL
- for intermediate certificate supports.
-
- @param[in] Status Original status before calling this callback.
- @param[in] Context X509 store context.
-
- @retval 1 Current X509 certificate is verified successfully.
- @retval 0 Verification failed.
-
-**/
-int
-X509VerifyCb (
- IN int Status,
- IN X509_STORE_CTX *Context
- )
-{
- X509_OBJECT *Obj;
- INTN Error;
- INTN Index;
- INTN Count;
-
- Obj = NULL;
- Error = (INTN) X509_STORE_CTX_get_error (Context);
-
- //
- // X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT and X509_V_ERR_UNABLE_TO_GET_ISSUER_
- // CERT_LOCALLY mean a X509 certificate is not self signed and its issuer
- // can not be found in X509_verify_cert of X509_vfy.c.
- // In order to support intermediate certificate node, we override the
- // errors if the certification is obtained from X509 store, i.e. it is
- // a trusted ceritifcate node that is enrolled by user.
- // Besides,X509_V_ERR_CERT_UNTRUSTED and X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
- // are also ignored to enable such feature.
- //
- if ((Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) ||
- (Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)) {
- Obj = (X509_OBJECT *) malloc (sizeof (X509_OBJECT));
- if (Obj == NULL) {
- return 0;
- }
-
- Obj->type = X509_LU_X509;
- Obj->data.x509 = Context->current_cert;
-
- CRYPTO_w_lock (CRYPTO_LOCK_X509_STORE);
-
- if (X509_OBJECT_retrieve_match (Context->ctx->objs, Obj)) {
- Status = 1;
- } else {
- //
- // If any certificate in the chain is enrolled as trusted certificate,
- // pass the certificate verification.
- //
- if (Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {
- Count = (INTN) sk_X509_num (Context->chain);
- for (Index = 0; Index < Count; Index++) {
- Obj->data.x509 = sk_X509_value (Context->chain, (int) Index);
- if (X509_OBJECT_retrieve_match (Context->ctx->objs, Obj)) {
- Status = 1;
- break;
- }
- }
- }
- }
-
- CRYPTO_w_unlock (CRYPTO_LOCK_X509_STORE);
- }
-
- if ((Error == X509_V_ERR_CERT_UNTRUSTED) ||
- (Error == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE)) {
- Status = 1;
- }
-
- if (Obj != NULL) {
- OPENSSL_free (Obj);
- }
-
- return Status;
-}
-
-/**
Check input P7Data is a wrapped ContentInfo structure or not. If not construct
a new structure to wrap P7Data.
@@ -509,6 +428,294 @@ Pkcs7FreeSigners ( }
/**
+ Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7:
+ Cryptographic Message Syntax Standard", and outputs two certificate lists chained and
+ unchained to the signer's certificates.
+ The input signed data could be wrapped in a ContentInfo structure.
+
+ @param[in] P7Data Pointer to the PKCS#7 message.
+ @param[in] P7Length Length of the PKCS#7 message in bytes.
+ @param[out] SignerChainCerts Pointer to the certificates list chained to signer's
+ certificate. It's caller's responsiblity to free the buffer.
+ @param[out] ChainLength Length of the chained certificates list buffer in bytes.
+ @param[out] UnchainCerts Pointer to the unchained certificates lists. It's caller's
+ responsiblity to free the buffer.
+ @param[out] UnchainLength Length of the unchained certificates list buffer in bytes.
+
+ @retval TRUE The operation is finished successfully.
+ @retval FALSE Error occurs during the operation.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs7GetCertificatesList (
+ IN CONST UINT8 *P7Data,
+ IN UINTN P7Length,
+ OUT UINT8 **SignerChainCerts,
+ OUT UINTN *ChainLength,
+ OUT UINT8 **UnchainCerts,
+ OUT UINTN *UnchainLength
+ )
+{
+ BOOLEAN Status;
+ UINT8 *NewP7Data;
+ UINTN NewP7Length;
+ BOOLEAN Wrapped;
+ UINT8 Index;
+ PKCS7 *Pkcs7;
+ X509_STORE_CTX CertCtx;
+ STACK_OF(X509) *Signers;
+ X509 *Signer;
+ X509 *Cert;
+ X509 *TempCert;
+ X509 *Issuer;
+ UINT8 *CertBuf;
+ UINT8 *OldBuf;
+ UINTN BufferSize;
+ UINTN OldSize;
+ UINT8 *SingleCert;
+ UINTN CertSize;
+
+ //
+ // Initializations
+ //
+ Status = FALSE;
+ NewP7Data = NULL;
+ Pkcs7 = NULL;
+ Cert = NULL;
+ TempCert = NULL;
+ SingleCert = NULL;
+ CertBuf = NULL;
+ OldBuf = NULL;
+ Signers = NULL;
+
+ //
+ // Parameter Checking
+ //
+ if ((P7Data == NULL) || (SignerChainCerts == NULL) || (ChainLength == NULL) ||
+ (UnchainCerts == NULL) || (UnchainLength == NULL) || (P7Length > INT_MAX)) {
+ return Status;
+ }
+
+ *SignerChainCerts = NULL;
+ *ChainLength = 0;
+ *UnchainCerts = NULL;
+ *UnchainLength = 0;
+
+ //
+ // Construct a new PKCS#7 data wrapping with ContentInfo structure if needed.
+ //
+ Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &NewP7Data, &NewP7Length);
+ if (!Status || (NewP7Length > INT_MAX)) {
+ goto _Error;
+ }
+
+ //
+ // Decodes PKCS#7 SignedData
+ //
+ Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &NewP7Data, (int) NewP7Length);
+ if ((Pkcs7 == NULL) || (!PKCS7_type_is_signed (Pkcs7))) {
+ goto _Error;
+ }
+
+ //
+ // Obtains Signer's Certificate from PKCS#7 data
+ // NOTE: Only one signer case will be handled in this function, which means SignerInfos
+ // should include only one signer's certificate.
+ //
+ Signers = PKCS7_get0_signers (Pkcs7, NULL, PKCS7_BINARY);
+ if ((Signers == NULL) || (sk_X509_num (Signers) != 1)) {
+ goto _Error;
+ }
+ Signer = sk_X509_value (Signers, 0);
+
+ if (!X509_STORE_CTX_init (&CertCtx, NULL, Signer, Pkcs7->d.sign->cert)) {
+ goto _Error;
+ }
+ //
+ // Initialize Chained & Untrusted stack
+ //
+ if (CertCtx.chain == NULL) {
+ if (((CertCtx.chain = sk_X509_new_null ()) == NULL) ||
+ (!sk_X509_push (CertCtx.chain, CertCtx.cert))) {
+ goto _Error;
+ }
+ }
+ (VOID)sk_X509_delete_ptr (CertCtx.untrusted, Signer);
+
+ //
+ // Build certificates stack chained from Signer's certificate.
+ //
+ Cert = Signer;
+ for (; ;) {
+ //
+ // Self-Issue checking
+ //
+ if (CertCtx.check_issued (&CertCtx, Cert, Cert)) {
+ break;
+ }
+
+ //
+ // Found the issuer of the current certificate
+ //
+ if (CertCtx.untrusted != NULL) {
+ Issuer = NULL;
+ for (Index = 0; Index < sk_X509_num (CertCtx.untrusted); Index++) {
+ TempCert = sk_X509_value (CertCtx.untrusted, Index);
+ if (CertCtx.check_issued (&CertCtx, Cert, TempCert)) {
+ Issuer = TempCert;
+ break;
+ }
+ }
+ if (Issuer != NULL) {
+ if (!sk_X509_push (CertCtx.chain, Issuer)) {
+ goto _Error;
+ }
+ (VOID)sk_X509_delete_ptr (CertCtx.untrusted, Issuer);
+
+ Cert = Issuer;
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ //
+ // Converts Chained and Untrusted Certificate to Certificate Buffer in following format:
+ // UINT8 CertNumber;
+ // UINT32 Cert1Length;
+ // UINT8 Cert1[];
+ // UINT32 Cert2Length;
+ // UINT8 Cert2[];
+ // ...
+ // UINT32 CertnLength;
+ // UINT8 Certn[];
+ //
+
+ if (CertCtx.chain != NULL) {
+ BufferSize = sizeof (UINT8);
+ OldSize = BufferSize;
+ CertBuf = NULL;
+
+ for (Index = 0; ; Index++) {
+ Status = X509PopCertificate (CertCtx.chain, &SingleCert, &CertSize);
+ if (!Status) {
+ break;
+ }
+
+ OldSize = BufferSize;
+ OldBuf = CertBuf;
+ BufferSize = OldSize + CertSize + sizeof (UINT32);
+ CertBuf = malloc (BufferSize);
+
+ if (CertBuf == NULL) {
+ Status = FALSE;
+ goto _Error;
+ }
+ if (OldBuf != NULL) {
+ CopyMem (CertBuf, OldBuf, OldSize);
+ free (OldBuf);
+ OldBuf = NULL;
+ }
+
+ WriteUnaligned32 ((UINT32 *) (CertBuf + OldSize), (UINT32) CertSize);
+ CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, CertSize);
+
+ free (SingleCert);
+ SingleCert = NULL;
+ }
+
+ if (CertBuf != NULL) {
+ //
+ // Update CertNumber.
+ //
+ CertBuf[0] = Index;
+
+ *SignerChainCerts = CertBuf;
+ *ChainLength = BufferSize;
+ }
+ }
+
+ if (CertCtx.untrusted != NULL) {
+ BufferSize = sizeof (UINT8);
+ OldSize = BufferSize;
+ CertBuf = NULL;
+
+ for (Index = 0; ; Index++) {
+ Status = X509PopCertificate (CertCtx.untrusted, &SingleCert, &CertSize);
+ if (!Status) {
+ break;
+ }
+
+ OldSize = BufferSize;
+ OldBuf = CertBuf;
+ BufferSize = OldSize + CertSize + sizeof (UINT32);
+ CertBuf = malloc (BufferSize);
+
+ if (CertBuf == NULL) {
+ Status = FALSE;
+ goto _Error;
+ }
+ if (OldBuf != NULL) {
+ CopyMem (CertBuf, OldBuf, OldSize);
+ free (OldBuf);
+ OldBuf = NULL;
+ }
+
+ WriteUnaligned32 ((UINT32 *) (CertBuf + OldSize), (UINT32) CertSize);
+ CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, CertSize);
+
+ free (SingleCert);
+ SingleCert = NULL;
+ }
+
+ if (CertBuf != NULL) {
+ //
+ // Update CertNumber.
+ //
+ CertBuf[0] = Index;
+
+ *UnchainCerts = CertBuf;
+ *UnchainLength = BufferSize;
+ }
+ }
+
+ Status = TRUE;
+
+_Error:
+ //
+ // Release Resources.
+ //
+ if (!Wrapped && (NewP7Data != NULL)) {
+ free (NewP7Data);
+ }
+
+ if (Pkcs7 != NULL) {
+ PKCS7_free (Pkcs7);
+ }
+ sk_X509_free (Signers);
+
+ X509_STORE_CTX_cleanup (&CertCtx);
+
+ if (SingleCert != NULL) {
+ free (SingleCert);
+ }
+
+ if (OldBuf != NULL) {
+ free (OldBuf);
+ }
+
+ if (!Status && (CertBuf != NULL)) {
+ free (CertBuf);
+ *SignerChainCerts = NULL;
+ *UnchainCerts = NULL;
+ }
+
+ return Status;
+}
+
+/**
Verifies the validility of a PKCS#7 signed data as described in "PKCS #7:
Cryptographic Message Syntax Standard". The input signed data could be wrapped
in a ContentInfo structure.
@@ -636,12 +843,6 @@ Pkcs7Verify ( }
//
- // Register customized X509 verification callback function to support
- // trusted intermediate certificate anchor.
- //
- CertStore->verify_cb = X509VerifyCb;
-
- //
// For generic PKCS#7 handling, InData may be NULL if the content is present
// in PKCS#7 structure. So ignore NULL checking here.
//
@@ -655,6 +856,13 @@ Pkcs7Verify ( }
//
+ // Allow partial certificate chains, terminated by a non-self-signed but
+ // still trusted intermediate certificate. Also disable time checks.
+ //
+ X509_STORE_set_flags (CertStore,
+ X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME);
+
+ //
// OpenSSL PKCS7 Verification by default checks for SMIME (email signing) and
// doesn't support the extended key usage for Authenticode Code Signing.
// Bypass the certificate purpose checking by enabling any purposes setting.
|
