Add a bunch of compatibility functions for PKCS#7.
The full library is a bit much, but this is enough to appease most of cryptography.io. Change-Id: I1bb0d83744c4550d5fe23c5c98cfd7e36b17fcc9 Reviewed-on: https://boringssl-review.googlesource.com/29365 Reviewed-by: Adam Langley <agl@google.com> Commit-Queue: Adam Langley <agl@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
parent
eaf0a17db8
commit
3815720cf3
@ -113,9 +113,7 @@
|
|||||||
#include <openssl/dsa.h>
|
#include <openssl/dsa.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
/*
|
#include <openssl/pkcs7.h>
|
||||||
* #include <openssl/pkcs7.h>
|
|
||||||
*/
|
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
@ -127,6 +125,7 @@ IMPLEMENT_PEM_rw(X509_REQ, X509_REQ, PEM_STRING_X509_REQ, X509_REQ)
|
|||||||
|
|
||||||
IMPLEMENT_PEM_write(X509_REQ_NEW, X509_REQ, PEM_STRING_X509_REQ_OLD, X509_REQ)
|
IMPLEMENT_PEM_write(X509_REQ_NEW, X509_REQ, PEM_STRING_X509_REQ_OLD, X509_REQ)
|
||||||
IMPLEMENT_PEM_rw(X509_CRL, X509_CRL, PEM_STRING_X509_CRL, X509_CRL)
|
IMPLEMENT_PEM_rw(X509_CRL, X509_CRL, PEM_STRING_X509_CRL, X509_CRL)
|
||||||
|
IMPLEMENT_PEM_rw(PKCS7, PKCS7, PEM_STRING_PKCS7, PKCS7)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We treat RSA or DSA private keys as a special case. For private keys we
|
* We treat RSA or DSA private keys as a special case. For private keys we
|
||||||
|
@ -493,7 +493,6 @@ static void TestCertRepase(const uint8_t *der_bytes, size_t der_len) {
|
|||||||
EXPECT_EQ(0u, CBS_len(&pkcs7));
|
EXPECT_EQ(0u, CBS_len(&pkcs7));
|
||||||
|
|
||||||
ASSERT_EQ(sk_X509_num(certs.get()), sk_X509_num(certs2.get()));
|
ASSERT_EQ(sk_X509_num(certs.get()), sk_X509_num(certs2.get()));
|
||||||
|
|
||||||
for (size_t i = 0; i < sk_X509_num(certs.get()); i++) {
|
for (size_t i = 0; i < sk_X509_num(certs.get()); i++) {
|
||||||
X509 *a = sk_X509_value(certs.get(), i);
|
X509 *a = sk_X509_value(certs.get(), i);
|
||||||
X509 *b = sk_X509_value(certs2.get(), i);
|
X509 *b = sk_X509_value(certs2.get(), i);
|
||||||
@ -506,6 +505,50 @@ static void TestCertRepase(const uint8_t *der_bytes, size_t der_len) {
|
|||||||
bssl::UniquePtr<uint8_t> free_result2_data(result2_data);
|
bssl::UniquePtr<uint8_t> free_result2_data(result2_data);
|
||||||
|
|
||||||
EXPECT_EQ(Bytes(result_data, result_len), Bytes(result2_data, result2_len));
|
EXPECT_EQ(Bytes(result_data, result_len), Bytes(result2_data, result2_len));
|
||||||
|
|
||||||
|
// Parse with the legacy API instead.
|
||||||
|
const uint8_t *ptr = der_bytes;
|
||||||
|
bssl::UniquePtr<PKCS7> pkcs7_obj(d2i_PKCS7(nullptr, &ptr, der_len));
|
||||||
|
ASSERT_TRUE(pkcs7_obj);
|
||||||
|
EXPECT_EQ(ptr, der_bytes + der_len);
|
||||||
|
|
||||||
|
ASSERT_TRUE(PKCS7_type_is_signed(pkcs7_obj.get()));
|
||||||
|
const STACK_OF(X509) *certs3 = pkcs7_obj->d.sign->cert;
|
||||||
|
ASSERT_EQ(sk_X509_num(certs.get()), sk_X509_num(certs3));
|
||||||
|
for (size_t i = 0; i < sk_X509_num(certs.get()); i++) {
|
||||||
|
X509 *a = sk_X509_value(certs.get(), i);
|
||||||
|
X509 *b = sk_X509_value(certs3, i);
|
||||||
|
ASSERT_EQ(0, X509_cmp(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize the original object. This should echo back the original saved
|
||||||
|
// bytes.
|
||||||
|
uint8_t *result3_data = nullptr;
|
||||||
|
int result3_len = i2d_PKCS7(pkcs7_obj.get(), &result3_data);
|
||||||
|
ASSERT_GT(result3_len, 0);
|
||||||
|
bssl::UniquePtr<uint8_t> free_result3_data(result3_data);
|
||||||
|
EXPECT_EQ(Bytes(der_bytes, der_len), Bytes(result3_data, result3_len));
|
||||||
|
|
||||||
|
// Make a new object with the legacy API.
|
||||||
|
pkcs7_obj.reset(
|
||||||
|
PKCS7_sign(nullptr, nullptr, certs.get(), nullptr, PKCS7_DETACHED));
|
||||||
|
ASSERT_TRUE(pkcs7_obj);
|
||||||
|
|
||||||
|
ASSERT_TRUE(PKCS7_type_is_signed(pkcs7_obj.get()));
|
||||||
|
const STACK_OF(X509) *certs4 = pkcs7_obj->d.sign->cert;
|
||||||
|
ASSERT_EQ(sk_X509_num(certs.get()), sk_X509_num(certs4));
|
||||||
|
for (size_t i = 0; i < sk_X509_num(certs.get()); i++) {
|
||||||
|
X509 *a = sk_X509_value(certs.get(), i);
|
||||||
|
X509 *b = sk_X509_value(certs4, i);
|
||||||
|
ASSERT_EQ(0, X509_cmp(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
// This new object should serialize canonically.
|
||||||
|
uint8_t *result4_data = nullptr;
|
||||||
|
int result4_len = i2d_PKCS7(pkcs7_obj.get(), &result4_data);
|
||||||
|
ASSERT_GT(result4_len, 0);
|
||||||
|
bssl::UniquePtr<uint8_t> free_result4_data(result4_data);
|
||||||
|
EXPECT_EQ(Bytes(result_data, result_len), Bytes(result4_data, result4_len));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TestCRLReparse(const uint8_t *der_bytes, size_t der_len) {
|
static void TestCRLReparse(const uint8_t *der_bytes, size_t der_len) {
|
||||||
@ -532,7 +575,6 @@ static void TestCRLReparse(const uint8_t *der_bytes, size_t der_len) {
|
|||||||
EXPECT_EQ(0u, CBS_len(&pkcs7));
|
EXPECT_EQ(0u, CBS_len(&pkcs7));
|
||||||
|
|
||||||
ASSERT_EQ(sk_X509_CRL_num(crls.get()), sk_X509_CRL_num(crls.get()));
|
ASSERT_EQ(sk_X509_CRL_num(crls.get()), sk_X509_CRL_num(crls.get()));
|
||||||
|
|
||||||
for (size_t i = 0; i < sk_X509_CRL_num(crls.get()); i++) {
|
for (size_t i = 0; i < sk_X509_CRL_num(crls.get()); i++) {
|
||||||
X509_CRL *a = sk_X509_CRL_value(crls.get(), i);
|
X509_CRL *a = sk_X509_CRL_value(crls.get(), i);
|
||||||
X509_CRL *b = sk_X509_CRL_value(crls2.get(), i);
|
X509_CRL *b = sk_X509_CRL_value(crls2.get(), i);
|
||||||
@ -545,6 +587,35 @@ static void TestCRLReparse(const uint8_t *der_bytes, size_t der_len) {
|
|||||||
bssl::UniquePtr<uint8_t> free_result2_data(result2_data);
|
bssl::UniquePtr<uint8_t> free_result2_data(result2_data);
|
||||||
|
|
||||||
EXPECT_EQ(Bytes(result_data, result_len), Bytes(result2_data, result2_len));
|
EXPECT_EQ(Bytes(result_data, result_len), Bytes(result2_data, result2_len));
|
||||||
|
|
||||||
|
// Parse with the legacy API instead.
|
||||||
|
const uint8_t *ptr = der_bytes;
|
||||||
|
bssl::UniquePtr<PKCS7> pkcs7_obj(d2i_PKCS7(nullptr, &ptr, der_len));
|
||||||
|
ASSERT_TRUE(pkcs7_obj);
|
||||||
|
EXPECT_EQ(ptr, der_bytes + der_len);
|
||||||
|
|
||||||
|
ASSERT_TRUE(PKCS7_type_is_signed(pkcs7_obj.get()));
|
||||||
|
const STACK_OF(X509_CRL) *crls3 = pkcs7_obj->d.sign->crl;
|
||||||
|
ASSERT_EQ(sk_X509_CRL_num(crls.get()), sk_X509_CRL_num(crls3));
|
||||||
|
for (size_t i = 0; i < sk_X509_CRL_num(crls.get()); i++) {
|
||||||
|
X509_CRL *a = sk_X509_CRL_value(crls.get(), i);
|
||||||
|
X509_CRL *b = sk_X509_CRL_value(crls3, i);
|
||||||
|
ASSERT_EQ(0, X509_CRL_cmp(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = result_data;
|
||||||
|
pkcs7_obj.reset(d2i_PKCS7(nullptr, &ptr, result_len));
|
||||||
|
ASSERT_TRUE(pkcs7_obj);
|
||||||
|
EXPECT_EQ(ptr, result_data + result_len);
|
||||||
|
|
||||||
|
ASSERT_TRUE(PKCS7_type_is_signed(pkcs7_obj.get()));
|
||||||
|
const STACK_OF(X509_CRL) *crls4 = pkcs7_obj->d.sign->crl;
|
||||||
|
ASSERT_EQ(sk_X509_CRL_num(crls.get()), sk_X509_CRL_num(crls4));
|
||||||
|
for (size_t i = 0; i < sk_X509_CRL_num(crls.get()); i++) {
|
||||||
|
X509_CRL *a = sk_X509_CRL_value(crls.get(), i);
|
||||||
|
X509_CRL *b = sk_X509_CRL_value(crls4, i);
|
||||||
|
ASSERT_EQ(0, X509_CRL_cmp(a, b));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TestPEMCerts(const char *pem) {
|
static void TestPEMCerts(const char *pem) {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "../internal.h"
|
||||||
|
|
||||||
|
|
||||||
int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
|
int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
|
||||||
@ -227,3 +228,168 @@ static int pkcs7_bundle_crls_cb(CBB *out, const void *arg) {
|
|||||||
int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) {
|
int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) {
|
||||||
return pkcs7_bundle(out, pkcs7_bundle_crls_cb, crls);
|
return pkcs7_bundle(out, pkcs7_bundle_crls_cb, crls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PKCS7 *pkcs7_new(CBS *cbs) {
|
||||||
|
PKCS7 *ret = OPENSSL_malloc(sizeof(PKCS7));
|
||||||
|
if (ret == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
OPENSSL_memset(ret, 0, sizeof(PKCS7));
|
||||||
|
ret->type = (ASN1_OBJECT *)OBJ_nid2obj(NID_pkcs7_signed);
|
||||||
|
ret->d.sign = OPENSSL_malloc(sizeof(PKCS7_SIGNED));
|
||||||
|
if (ret->d.sign == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
ret->d.sign->cert = sk_X509_new_null();
|
||||||
|
ret->d.sign->crl = sk_X509_CRL_new_null();
|
||||||
|
CBS copy = *cbs, copy2 = *cbs;
|
||||||
|
if (ret->d.sign->cert == NULL || ret->d.sign->crl == NULL ||
|
||||||
|
!PKCS7_get_certificates(ret->d.sign->cert, ©) ||
|
||||||
|
!PKCS7_get_CRLs(ret->d.sign->crl, cbs)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sk_X509_num(ret->d.sign->cert) == 0) {
|
||||||
|
sk_X509_free(ret->d.sign->cert);
|
||||||
|
ret->d.sign->cert = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sk_X509_CRL_num(ret->d.sign->crl) == 0) {
|
||||||
|
sk_X509_CRL_free(ret->d.sign->crl);
|
||||||
|
ret->d.sign->crl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret->ber_len = CBS_len(©2) - CBS_len(cbs);
|
||||||
|
ret->ber_bytes = BUF_memdup(CBS_data(©2), ret->ber_len);
|
||||||
|
if (ret->ber_bytes == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
err:
|
||||||
|
PKCS7_free(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PKCS7 *d2i_PKCS7(PKCS7 **out, const uint8_t **inp,
|
||||||
|
size_t len) {
|
||||||
|
CBS cbs;
|
||||||
|
CBS_init(&cbs, *inp, len);
|
||||||
|
PKCS7 *ret = pkcs7_new(&cbs);
|
||||||
|
if (ret == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*inp = CBS_data(&cbs);
|
||||||
|
if (out != NULL) {
|
||||||
|
PKCS7_free(*out);
|
||||||
|
*out = ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
PKCS7 *d2i_PKCS7_bio(BIO *bio, PKCS7 **out) {
|
||||||
|
// Use a generous bound, to allow for PKCS#7 files containing large root sets.
|
||||||
|
static const size_t kMaxSize = 4 * 1024 * 1024;
|
||||||
|
uint8_t *data;
|
||||||
|
size_t len;
|
||||||
|
if (!BIO_read_asn1(bio, &data, &len, kMaxSize)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBS cbs;
|
||||||
|
CBS_init(&cbs, data, len);
|
||||||
|
PKCS7 *ret = pkcs7_new(&cbs);
|
||||||
|
OPENSSL_free(data);
|
||||||
|
if (out != NULL && ret != NULL) {
|
||||||
|
PKCS7_free(*out);
|
||||||
|
*out = ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i2d_PKCS7(const PKCS7 *p7, uint8_t **out) {
|
||||||
|
if (p7->ber_len > INT_MAX) {
|
||||||
|
OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out == NULL) {
|
||||||
|
return (int)p7->ber_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*out == NULL) {
|
||||||
|
*out = OPENSSL_malloc(p7->ber_len);
|
||||||
|
if (*out == NULL) {
|
||||||
|
OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
OPENSSL_memcpy(*out, p7->ber_bytes, p7->ber_len);
|
||||||
|
} else {
|
||||||
|
OPENSSL_memcpy(*out, p7->ber_bytes, p7->ber_len);
|
||||||
|
*out += p7->ber_len;
|
||||||
|
}
|
||||||
|
return (int)p7->ber_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i2d_PKCS7_bio(BIO *bio, const PKCS7 *p7) {
|
||||||
|
size_t written = 0;
|
||||||
|
while (written < p7->ber_len) {
|
||||||
|
size_t todo = p7->ber_len - written;
|
||||||
|
int len = todo > INT_MAX ? INT_MAX : (int)todo;
|
||||||
|
int ret = BIO_write(bio, p7->ber_bytes + written, len);
|
||||||
|
if (ret <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
written += (size_t)ret;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PKCS7_free(PKCS7 *p7) {
|
||||||
|
if (p7 == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OPENSSL_free(p7->ber_bytes);
|
||||||
|
ASN1_OBJECT_free(p7->type);
|
||||||
|
// We only supported signed data.
|
||||||
|
if (p7->d.sign != NULL) {
|
||||||
|
sk_X509_pop_free(p7->d.sign->cert, X509_free);
|
||||||
|
sk_X509_CRL_pop_free(p7->d.sign->crl, X509_CRL_free);
|
||||||
|
OPENSSL_free(p7->d.sign);
|
||||||
|
}
|
||||||
|
OPENSSL_free(p7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only support signed data, so these getters are no-ops.
|
||||||
|
int PKCS7_type_is_data(const PKCS7 *p7) { return 0; }
|
||||||
|
int PKCS7_type_is_digest(const PKCS7 *p7) { return 0; }
|
||||||
|
int PKCS7_type_is_encrypted(const PKCS7 *p7) { return 0; }
|
||||||
|
int PKCS7_type_is_enveloped(const PKCS7 *p7) { return 0; }
|
||||||
|
int PKCS7_type_is_signed(const PKCS7 *p7) { return 1; }
|
||||||
|
int PKCS7_type_is_signedAndEnveloped(const PKCS7 *p7) { return 0; }
|
||||||
|
|
||||||
|
PKCS7 *PKCS7_sign(X509 *sign_cert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
|
||||||
|
BIO *data, int flags) {
|
||||||
|
if (sign_cert != NULL || pkey != NULL || flags != PKCS7_DETACHED) {
|
||||||
|
OPENSSL_PUT_ERROR(PKCS7, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *der;
|
||||||
|
size_t len;
|
||||||
|
CBB cbb;
|
||||||
|
if (!CBB_init(&cbb, 2048) ||
|
||||||
|
!PKCS7_bundle_certificates(&cbb, certs) ||
|
||||||
|
!CBB_finish(&cbb, &der, &len)) {
|
||||||
|
CBB_cleanup(&cbb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBS cbs;
|
||||||
|
CBS_init(&cbs, der, len);
|
||||||
|
PKCS7 *ret = pkcs7_new(&cbs);
|
||||||
|
OPENSSL_free(der);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
#include <openssl/digest.h>
|
#include <openssl/digest.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/stack.h>
|
#include <openssl/stack.h>
|
||||||
|
#include <openssl/pkcs7.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
/* For compatibility with open-iscsi, which assumes that it can get
|
/* For compatibility with open-iscsi, which assumes that it can get
|
||||||
@ -329,6 +330,7 @@ DECLARE_PEM_write(X509_REQ_NEW, X509_REQ)
|
|||||||
|
|
||||||
DECLARE_PEM_rw(X509_CRL, X509_CRL)
|
DECLARE_PEM_rw(X509_CRL, X509_CRL)
|
||||||
|
|
||||||
|
DECLARE_PEM_rw(PKCS7, PKCS7)
|
||||||
DECLARE_PEM_rw(PKCS8, X509_SIG)
|
DECLARE_PEM_rw(PKCS8, X509_SIG)
|
||||||
|
|
||||||
DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
|
DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
|
||||||
|
@ -82,8 +82,129 @@ OPENSSL_EXPORT int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls,
|
|||||||
BIO *pem_bio);
|
BIO *pem_bio);
|
||||||
|
|
||||||
|
|
||||||
|
// Deprecated functions.
|
||||||
|
//
|
||||||
|
// These functions are a compatibility layer over a subset of OpenSSL's PKCS#7
|
||||||
|
// API. It intentionally does not implement the whole thing, only the minimum
|
||||||
|
// needed to build cryptography.io.
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
STACK_OF(X509) *cert;
|
||||||
|
STACK_OF(X509_CRL) *crl;
|
||||||
|
} PKCS7_SIGNED;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
STACK_OF(X509) *cert;
|
||||||
|
STACK_OF(X509_CRL) *crl;
|
||||||
|
} PKCS7_SIGN_ENVELOPE;
|
||||||
|
|
||||||
|
typedef void PKCS7_ENVELOPE;
|
||||||
|
typedef void PKCS7_DIGEST;
|
||||||
|
typedef void PKCS7_ENCRYPT;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t *ber_bytes;
|
||||||
|
size_t ber_len;
|
||||||
|
|
||||||
|
// Unlike OpenSSL, the following fields are immutable. They filled in when the
|
||||||
|
// object is parsed and ignored in serialization.
|
||||||
|
ASN1_OBJECT *type;
|
||||||
|
union {
|
||||||
|
char *ptr;
|
||||||
|
ASN1_OCTET_STRING *data;
|
||||||
|
PKCS7_SIGNED *sign;
|
||||||
|
PKCS7_ENVELOPE *enveloped;
|
||||||
|
PKCS7_SIGN_ENVELOPE *signed_and_enveloped;
|
||||||
|
PKCS7_DIGEST *digest;
|
||||||
|
PKCS7_ENCRYPT *encrypted;
|
||||||
|
ASN1_TYPE *other;
|
||||||
|
} d;
|
||||||
|
} PKCS7;
|
||||||
|
|
||||||
|
// d2i_PKCS7 parses a BER-encoded, PKCS#7 signed data ContentInfo structure from
|
||||||
|
// |len| bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the
|
||||||
|
// result is in |*out|. Note that, even if |*out| is already non-NULL on entry,
|
||||||
|
// it will not be written to. Rather, a fresh |PKCS7| is allocated and the
|
||||||
|
// previous one is freed. On successful exit, |*inp| is advanced past the BER
|
||||||
|
// structure. It returns the result or NULL on error.
|
||||||
|
OPENSSL_EXPORT PKCS7 *d2i_PKCS7(PKCS7 **out, const uint8_t **inp,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
|
// d2i_PKCS7_bio behaves like |d2i_PKCS7| but reads the input from |bio|. If
|
||||||
|
// the length of the object is indefinite the full contents of |bio| are read.
|
||||||
|
//
|
||||||
|
// If the function fails then some unknown amount of data may have been read
|
||||||
|
// from |bio|.
|
||||||
|
OPENSSL_EXPORT PKCS7 *d2i_PKCS7_bio(BIO *bio, PKCS7 **out);
|
||||||
|
|
||||||
|
// i2d_PKCS7 is a dummy function which copies the contents of |p7|. If |out| is
|
||||||
|
// not NULL then the result is written to |*out| and |*out| is advanced just
|
||||||
|
// past the output. It returns the number of bytes in the result, whether
|
||||||
|
// written or not, or a negative value on error.
|
||||||
|
OPENSSL_EXPORT int i2d_PKCS7(const PKCS7 *p7, uint8_t **out);
|
||||||
|
|
||||||
|
// i2d_PKCS7_bio writes |p7| to |bio|. It returns one on success and zero on
|
||||||
|
// error.
|
||||||
|
OPENSSL_EXPORT int i2d_PKCS7_bio(BIO *bio, const PKCS7 *p7);
|
||||||
|
|
||||||
|
// PKCS7_free releases memory associated with |p7|.
|
||||||
|
OPENSSL_EXPORT void PKCS7_free(PKCS7 *p7);
|
||||||
|
|
||||||
|
// PKCS7_type_is_data returns zero.
|
||||||
|
OPENSSL_EXPORT int PKCS7_type_is_data(const PKCS7 *p7);
|
||||||
|
|
||||||
|
// PKCS7_type_is_digest returns zero.
|
||||||
|
OPENSSL_EXPORT int PKCS7_type_is_digest(const PKCS7 *p7);
|
||||||
|
|
||||||
|
// PKCS7_type_is_encrypted returns zero.
|
||||||
|
OPENSSL_EXPORT int PKCS7_type_is_encrypted(const PKCS7 *p7);
|
||||||
|
|
||||||
|
// PKCS7_type_is_enveloped returns zero.
|
||||||
|
OPENSSL_EXPORT int PKCS7_type_is_enveloped(const PKCS7 *p7);
|
||||||
|
|
||||||
|
// PKCS7_type_is_signed returns one. (We only supporte signed data
|
||||||
|
// ContentInfos.)
|
||||||
|
OPENSSL_EXPORT int PKCS7_type_is_signed(const PKCS7 *p7);
|
||||||
|
|
||||||
|
// PKCS7_type_is_signedAndEnveloped returns zero.
|
||||||
|
OPENSSL_EXPORT int PKCS7_type_is_signedAndEnveloped(const PKCS7 *p7);
|
||||||
|
|
||||||
|
// PKCS7_DETACHED indicates that the PKCS#7 file specifies its data externally.
|
||||||
|
#define PKCS7_DETACHED 0x40
|
||||||
|
|
||||||
|
// The following flags cause |PKCS7_sign| to fail.
|
||||||
|
#define PKCS7_TEXT 0x1
|
||||||
|
#define PKCS7_NOCERTS 0x2
|
||||||
|
#define PKCS7_NOSIGS 0x4
|
||||||
|
#define PKCS7_NOCHAIN 0x8
|
||||||
|
#define PKCS7_NOINTERN 0x10
|
||||||
|
#define PKCS7_NOVERIFY 0x20
|
||||||
|
#define PKCS7_BINARY 0x80
|
||||||
|
#define PKCS7_NOATTR 0x100
|
||||||
|
#define PKCS7_NOSMIMECAP 0x200
|
||||||
|
#define PKCS7_STREAM 0x1000
|
||||||
|
|
||||||
|
// PKCS7_sign assembles |certs| into a PKCS#7 signed data ContentInfo with
|
||||||
|
// external data and no signatures. It returns a newly-allocated |PKCS7| on
|
||||||
|
// success or NULL on error. |sign_cert| and |pkey| must be NULL. |data| is
|
||||||
|
// ignored. |flags| must be equal to |PKCS7_DETACHED|.
|
||||||
|
//
|
||||||
|
// Note this function only implements a subset of the corresponding OpenSSL
|
||||||
|
// function. It is provided for backwards compatibility only.
|
||||||
|
OPENSSL_EXPORT PKCS7 *PKCS7_sign(X509 *sign_cert, EVP_PKEY *pkey,
|
||||||
|
STACK_OF(X509) *certs, BIO *data, int flags);
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
} // extern C
|
} // extern C
|
||||||
|
|
||||||
|
extern "C++" {
|
||||||
|
namespace bssl {
|
||||||
|
|
||||||
|
BORINGSSL_MAKE_DELETER(PKCS7, PKCS7_free)
|
||||||
|
|
||||||
|
} // namespace bssl
|
||||||
|
} // extern C++
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PKCS7_R_BAD_PKCS7_VERSION 100
|
#define PKCS7_R_BAD_PKCS7_VERSION 100
|
||||||
|
Loading…
Reference in New Issue
Block a user