Skip to content

Commit

Permalink
Implement PKCS7_dataInit and PKCS7_dataFinal (#1816)
Browse files Browse the repository at this point in the history
This PR adds a few new functions, most notably `PKCS7_dataInit` and
`PKCS7_dataFinal` as they're used by ruby to prepare/finalize BIO chains
for reading from or writing to a PKCS7 object. Their usage is documented
here in `pkcs7.h`.
  • Loading branch information
WillChilds-Klein authored Nov 18, 2024
1 parent 404fe0f commit 318413c
Show file tree
Hide file tree
Showing 8 changed files with 892 additions and 17 deletions.
10 changes: 5 additions & 5 deletions crypto/pkcs7/bio/bio_md_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ TEST_P(BIOMessageDigestTest, Basic) {
bio_md.reset(BIO_new(BIO_f_md()));
ASSERT_TRUE(bio_md);
EXPECT_FALSE(BIO_reset(bio_md.get()));
EXPECT_TRUE(BIO_set_md(bio_md.get(), (EVP_MD *)md));
EXPECT_TRUE(BIO_set_md(bio_md.get(), md));
EVP_MD_CTX *ctx_tmp; // |bio_md| owns the context, we just take a ref here
EXPECT_TRUE(BIO_get_md_ctx(bio_md.get(), &ctx_tmp));
EXPECT_EQ(EVP_MD_type(md), EVP_MD_CTX_type(ctx_tmp));
Expand Down Expand Up @@ -98,7 +98,7 @@ TEST_P(BIOMessageDigestTest, Basic) {
// Write-through digest BIO
bio_md.reset(BIO_new(BIO_f_md()));
ASSERT_TRUE(bio_md);
EXPECT_TRUE(BIO_set_md(bio_md.get(), (void *)md));
EXPECT_TRUE(BIO_set_md(bio_md.get(), md));
bio_mem.reset(BIO_new(BIO_s_mem()));
ASSERT_TRUE(bio_mem);
bio.reset(BIO_push(bio_md.get(), bio_mem.get()));
Expand Down Expand Up @@ -126,7 +126,7 @@ TEST_P(BIOMessageDigestTest, Basic) {
// Read-through digest BIO
bio_md.reset(BIO_new(BIO_f_md()));
ASSERT_TRUE(bio_md);
EXPECT_TRUE(BIO_set_md(bio_md.get(), (void *)md));
EXPECT_TRUE(BIO_set_md(bio_md.get(), md));
bio_mem.reset(BIO_new_mem_buf(message, sizeof(message)));
ASSERT_TRUE(bio_mem);
bio.reset(BIO_push(bio_md.get(), bio_mem.get()));
Expand Down Expand Up @@ -208,7 +208,7 @@ TEST_P(BIOMessageDigestTest, Randomized) {
// Write-through digest BIO, check against expectation
bio_md.reset(BIO_new(BIO_f_md()));
ASSERT_TRUE(bio_md);
EXPECT_TRUE(BIO_set_md(bio_md.get(), (void *)md));
EXPECT_TRUE(BIO_set_md(bio_md.get(), md));
bio_mem.reset(BIO_new(BIO_s_mem()));
ASSERT_TRUE(bio_mem);
bio.reset(BIO_push(bio_md.get(), bio_mem.get()));
Expand All @@ -232,7 +232,7 @@ TEST_P(BIOMessageDigestTest, Randomized) {
// Read-through digest BIO, check against expectation
bio_md.reset(BIO_new(BIO_f_md()));
ASSERT_TRUE(bio_md);
EXPECT_TRUE(BIO_set_md(bio_md.get(), (void *)md));
EXPECT_TRUE(BIO_set_md(bio_md.get(), md));
bio_mem.reset(BIO_new_mem_buf(message.data(), message.size()));
ASSERT_TRUE(bio_mem);
bio.reset(BIO_push(bio_md.get(), bio_mem.get()));
Expand Down
15 changes: 14 additions & 1 deletion crypto/pkcs7/bio/cipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ static long enc_ctrl(BIO *b, int cmd, long num, void *ptr) {
long ret = 1;

BIO_ENC_CTX *ctx = BIO_get_data(b);
EVP_CIPHER_CTX **cipher_ctx;
BIO *next = BIO_next(b);
if (ctx == NULL) {
return 0;
Expand Down Expand Up @@ -241,6 +242,15 @@ static long enc_ctrl(BIO *b, int cmd, long num, void *ptr) {
case BIO_C_GET_CIPHER_STATUS:
ret = (long)ctx->ok;
break;
case BIO_C_GET_CIPHER_CTX:
cipher_ctx = (EVP_CIPHER_CTX **)ptr;
if (!cipher_ctx) {
ret = 0;
break;
}
*cipher_ctx = ctx->cipher;
BIO_set_init(b, 1);
break;
// OpenSSL implements these, but because we don't need them and cipher BIO
// is internal, we can fail loudly if they're called. If this case is hit,
// it likely means you're making a change that will require implementing
Expand All @@ -249,7 +259,6 @@ static long enc_ctrl(BIO *b, int cmd, long num, void *ptr) {
case BIO_CTRL_GET_CALLBACK:
case BIO_CTRL_SET_CALLBACK:
case BIO_C_DO_STATE_MACHINE:
case BIO_C_GET_CIPHER_CTX:
OPENSSL_PUT_ERROR(PKCS7, ERR_R_BIO_LIB);
return 0;
default:
Expand Down Expand Up @@ -313,3 +322,7 @@ static const BIO_METHOD methods_enc = {
};

const BIO_METHOD *BIO_f_cipher(void) { return &methods_enc; }

int BIO_get_cipher_ctx(BIO *b, EVP_CIPHER_CTX **ctx) {
return BIO_ctrl(b, BIO_C_GET_CIPHER_CTX, 0, ctx);
}
8 changes: 8 additions & 0 deletions crypto/pkcs7/bio/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,11 @@ static const BIO_METHOD methods_md = {
};

const BIO_METHOD *BIO_f_md(void) { return &methods_md; }

int BIO_get_md_ctx(BIO *b, EVP_MD_CTX **ctx) {
return BIO_ctrl(b, BIO_C_GET_MD_CTX, 0, ctx);
}

int BIO_set_md(BIO *b, const EVP_MD *md) {
return BIO_ctrl(b, BIO_C_SET_MD, 0, (EVP_MD*)md);
}
10 changes: 6 additions & 4 deletions crypto/pkcs7/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,23 +204,25 @@ int pkcs7_add_signed_data(CBB *out,
// |BIO_get_md_ctx| before it can be used.
OPENSSL_EXPORT const BIO_METHOD *BIO_f_md(void);

// BIO_get_md_ctx writes a reference of |b|'s EVP_MD_CTX* to |*mdcp|
#define BIO_get_md_ctx(b, mdcp) BIO_ctrl(b, BIO_C_GET_MD_CTX, 0, mdcp)
// BIO_get_md_ctx writes a reference of |b|'s EVP_MD_CTX* to |*ctx|
OPENSSL_EXPORT int BIO_get_md_ctx(BIO *b, EVP_MD_CTX **ctx);

// BIO_set_md set's |b|'s EVP_MD* to |md|
#define BIO_set_md(b, md) BIO_ctrl(b, BIO_C_SET_MD, 0, md)
OPENSSL_EXPORT int BIO_set_md(BIO *b, const EVP_MD *md);

// BIO_f_cipher is used internally by the pkcs7 module. It is not recommended
// for external use.
OPENSSL_EXPORT const BIO_METHOD *BIO_f_cipher(void);

// BIO_get_cipher_ctx writes a reference of |b|'s EVP_CIPHER_CTX* to |*ctx|
int BIO_get_cipher_ctx(BIO *b, EVP_CIPHER_CTX **ctx);

// BIO_set_cipher is used internally for testing. It is not recommended for
// external use.
OPENSSL_EXPORT int BIO_set_cipher(BIO *b, const EVP_CIPHER *cipher,
const unsigned char *key,
const unsigned char *iv, int enc);


#if defined(__cplusplus)
} // extern C
#endif
Expand Down
Loading

0 comments on commit 318413c

Please sign in to comment.