Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Ok, found all this out the (very) hard way. This is how you do it, so that others might learn more easily.</p> <p>Lets say we have the signature <code>char* sig</code> of length <code>int sig_length</code>, and verification data <code>char* data</code>, <code>int data_length</code>. (There are some subtleties here for PDF signatures but these are well documented in the PDF spec.)</p> <pre><code>OpenSSL_add_all_algorithms(); OpenSSL_add_all_digests(); EVP_add_digest(EVP_md5()); EVP_add_digest(EVP_sha1()); EVP_add_digest(EVP_sha256()); BIO* sig_BIO = BIO_new_mem_buf(sig, sig_length) PKCS7* sig_pkcs7 = d2i_PKCS7_bio(sig_BIO, NULL); BIO* data_BIO = BIO_new_mem_buf(data, data_length) BIO* data_pkcs7_BIO = PKCS7_dataInit(sig_pkcs7, data_BIO); // Goto this place in the BIO. Why? No idea! char unneeded[1024*4]; while (BIO_read(dataPKCS7_BIO, unneeded, sizeof(buffer)) &gt; 0); int result; X509_STORE *certificateStore = X509_STORE_new(); X509_STORE_CTX certificateContext; STACK_OF(PKCS7_SIGNER_INFO) *signerStack = PKCS7_get_signer_info(sig_pkcs7); int numSignerInfo = sk_PKCS7_SIGNER_INFO_num(signerStack); for (int i=0; i&lt;numSignerInfo; ++i) { PKCS7_SIGNER_INFO *signerInfo = sk_PKCS7_SIGNER_INFO_value(signerStack, i); result = PKCS7_dataVerify(certificateStore, &amp;certificateContext, data_pkcs7_BIO, sig_pkcs7, signerInfo); } X509_STORE_CTX_cleanup(&amp;certificateContext); BIO_free(sig_BIO); BIO_free(data_BIO); BIO_free(data_pkcs7_BIO); PKCS7_free(sig_pkcs7); X509_STORE_free(certificateStore); </code></pre> <p>The function that does the work is actually PKCS7_dataVerify, and you don't need to run any digests yourself.</p> <p>But wait, if you try this, it won't work! Why? Because the verification does both trust and integrity. In addition to this, you will also need to either establish trust by adding certs to the store, which is also complicated and undocumented. If you want fine grain results for you'll want to set a callback on the verification via the certificate store like this:</p> <pre><code>X509_VERIFY_PARAM_set_flags(certificateStore-&gt;param, X509_V_FLAG_CB_ISSUER_CHECK); X509_STORE_set_verify_cb_func(certificateStore, verificationCallback); </code></pre> <p>where</p> <pre><code>static int verificationCallback(int ok, X509_STORE_CTX *ctx) { switch (ctx-&gt;error) { case X509_V_ERR_INVALID_PURPOSE: //... case X509_V_ERR_CERT_HAS_EXPIRED: //... case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: //... case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: //... // ... etc default: break; } return ok; } </code></pre> <p>You can set the error to ok and tell it to verify, for example if you want to ignore expired certs:</p> <pre><code>static int verificationCallback(int ok, X509_STORE_CTX *ctx) { switch (ctx-&gt;error) { case X509_V_ERR_CERT_HAS_EXPIRED: X509_STORE_CTX_set_error(ctx, X509_V_OK); ok = 1; break; } return ok; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload