Skip to content

Commit 20ca7a2

Browse files
committed
pkcs7: keep private key when duplicating PKCS7_SIGNER_INFO
ASN1_dup() will not copy the 'pkey' field of a PKCS7_SIGNER_INFO object by design; it is a temporary field kept until the PKCS7 structure is finalized. Let's bump reference counter of the pkey in the original object and use it in the new object, too. This commit also removes PKCS7#add_signer's routine to add the content-type attribute as a signed attribute automatically. This behavior was not documented or tested. This change should not break any working user code since the method was completely useless without the change above.
1 parent 6e45755 commit 20ca7a2

File tree

2 files changed

+51
-48
lines changed

2 files changed

+51
-48
lines changed

ext/openssl/ossl_pkcs7.c

Lines changed: 33 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -101,19 +101,24 @@ static const rb_data_type_t ossl_pkcs7_recip_info_type = {
101101
* (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM)
102102
*/
103103
static PKCS7_SIGNER_INFO *
104-
ossl_PKCS7_SIGNER_INFO_dup(const PKCS7_SIGNER_INFO *si)
104+
ossl_PKCS7_SIGNER_INFO_dup(PKCS7_SIGNER_INFO *si)
105105
{
106-
return (PKCS7_SIGNER_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO,
107-
(d2i_of_void *)d2i_PKCS7_SIGNER_INFO,
108-
(char *)si);
106+
PKCS7_SIGNER_INFO *si_new = ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO,
107+
(d2i_of_void *)d2i_PKCS7_SIGNER_INFO,
108+
si);
109+
if (si_new && si->pkey) {
110+
EVP_PKEY_up_ref(si->pkey);
111+
si_new->pkey = si->pkey;
112+
}
113+
return si_new;
109114
}
110115

111116
static PKCS7_RECIP_INFO *
112-
ossl_PKCS7_RECIP_INFO_dup(const PKCS7_RECIP_INFO *si)
117+
ossl_PKCS7_RECIP_INFO_dup(PKCS7_RECIP_INFO *si)
113118
{
114-
return (PKCS7_RECIP_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO,
115-
(d2i_of_void *)d2i_PKCS7_RECIP_INFO,
116-
(char *)si);
119+
return ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO,
120+
(d2i_of_void *)d2i_PKCS7_RECIP_INFO,
121+
si);
117122
}
118123

119124
static VALUE
@@ -130,19 +135,6 @@ ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
130135
return obj;
131136
}
132137

133-
static PKCS7_SIGNER_INFO *
134-
DupPKCS7SignerPtr(VALUE obj)
135-
{
136-
PKCS7_SIGNER_INFO *p7si, *pkcs7;
137-
138-
GetPKCS7si(obj, p7si);
139-
if (!(pkcs7 = ossl_PKCS7_SIGNER_INFO_dup(p7si))) {
140-
ossl_raise(ePKCS7Error, NULL);
141-
}
142-
143-
return pkcs7;
144-
}
145-
146138
static VALUE
147139
ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri)
148140
{
@@ -157,19 +149,6 @@ ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri)
157149
return obj;
158150
}
159151

160-
static PKCS7_RECIP_INFO *
161-
DupPKCS7RecipientPtr(VALUE obj)
162-
{
163-
PKCS7_RECIP_INFO *p7ri, *pkcs7;
164-
165-
GetPKCS7ri(obj, p7ri);
166-
if (!(pkcs7 = ossl_PKCS7_RECIP_INFO_dup(p7ri))) {
167-
ossl_raise(ePKCS7Error, NULL);
168-
}
169-
170-
return pkcs7;
171-
}
172-
173152
/*
174153
* call-seq:
175154
* PKCS7.read_smime(string) => pkcs7
@@ -521,17 +500,18 @@ static VALUE
521500
ossl_pkcs7_add_signer(VALUE self, VALUE signer)
522501
{
523502
PKCS7 *pkcs7;
524-
PKCS7_SIGNER_INFO *p7si;
503+
PKCS7_SIGNER_INFO *si, *si_new;
525504

526-
p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */
527505
GetPKCS7(self, pkcs7);
528-
if (!PKCS7_add_signer(pkcs7, p7si)) {
529-
PKCS7_SIGNER_INFO_free(p7si);
530-
ossl_raise(ePKCS7Error, "Could not add signer.");
531-
}
532-
if (PKCS7_type_is_signed(pkcs7)){
533-
PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
534-
V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data));
506+
GetPKCS7si(signer, si);
507+
508+
si_new = ossl_PKCS7_SIGNER_INFO_dup(si);
509+
if (!si_new)
510+
ossl_raise(ePKCS7Error, "PKCS7_SIGNER_INFO_dup");
511+
512+
if (PKCS7_add_signer(pkcs7, si_new) != 1) {
513+
PKCS7_SIGNER_INFO_free(si_new);
514+
ossl_raise(ePKCS7Error, "PKCS7_add_signer");
535515
}
536516

537517
return self;
@@ -567,13 +547,18 @@ static VALUE
567547
ossl_pkcs7_add_recipient(VALUE self, VALUE recip)
568548
{
569549
PKCS7 *pkcs7;
570-
PKCS7_RECIP_INFO *ri;
550+
PKCS7_RECIP_INFO *ri, *ri_new;
571551

572-
ri = DupPKCS7RecipientPtr(recip); /* NEED TO DUP */
573552
GetPKCS7(self, pkcs7);
574-
if (!PKCS7_add_recipient_info(pkcs7, ri)) {
575-
PKCS7_RECIP_INFO_free(ri);
576-
ossl_raise(ePKCS7Error, "Could not add recipient.");
553+
GetPKCS7ri(recip, ri);
554+
555+
ri_new = ossl_PKCS7_RECIP_INFO_dup(ri);
556+
if (!ri_new)
557+
ossl_raise(ePKCS7Error, "PKCS7_RECIP_INFO_dup");
558+
559+
if (PKCS7_add_recipient_info(pkcs7, ri_new) != 1) {
560+
PKCS7_RECIP_INFO_free(ri_new);
561+
ossl_raise(ePKCS7Error, "PKCS7_add_recipient_info");
577562
}
578563

579564
return self;

test/openssl/test_pkcs7.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,24 @@ def test_signed
8989
assert_equal(@ee2_cert.issuer.to_s, signers[1].issuer.to_s)
9090
end
9191

92+
def test_signed_add_signer
93+
data = "aaaaa\nbbbbb\nccccc\n"
94+
psi = OpenSSL::PKCS7::SignerInfo.new(@ee1_cert, @rsa1024, "sha256")
95+
p7 = OpenSSL::PKCS7.new
96+
p7.type = :signed
97+
p7.add_signer(psi)
98+
p7.add_certificate(@ee1_cert)
99+
p7.add_certificate(@ca_cert)
100+
p7.add_data(data)
101+
102+
store = OpenSSL::X509::Store.new
103+
store.add_cert(@ca_cert)
104+
105+
assert_equal(true, p7.verify([], store))
106+
assert_equal(true, OpenSSL::PKCS7.new(p7.to_der).verify([], store))
107+
assert_equal(1, p7.signers.size)
108+
end
109+
92110
def test_detached_sign
93111
store = OpenSSL::X509::Store.new
94112
store.add_cert(@ca_cert)

0 commit comments

Comments
 (0)