Hi,
A collegue has an issue with SMIME_write_PKCS7() using Python and the
M2Crypto library for a multipart (MIME) signature. He uses a memory BIO
as output. He told me that the script works with OpenSSL 0.9.8g, but not
with OpenSSL 0.9.8o. In CVS, I saw that PKCS7 and ASN.1 code for SMIME
changed a lot, it is maybe a regression introduced by a code
factorization.
If data is not NULL, int_smime_write_ASN1() calls data_fn
(pk7_output_data() in my case) twice, and write into the output BIO
after the first call to data_fn. The problem is that PKCS7_dataFinal()
sets the output buffer to read only (I don't understood exactly in which
case).
M2Crypto adds PKCS7_DETACHED flag is data is not NULL. The real call
looks like:
SMIME_write_PKCS7(out, pkcs7, info, PKCS7_TEXT | PKCS7_DETACHED)
I am sorry, but I don't have a C script to reproduce the issue: only a
Python script (attached to this email, smime.py) using
flags=PKCS7_DETACHED. Output with error:
----
1 Error ?: None
2 Error ?: None
3 Error ?: None
4 Error ?: None
5 Error ?: None
6 Error ?: 139988672657152:error:2007507E:BIO routines:MEM_WRITE:write
to read only BIO:bss_mem.c:187:
139988672657152:error:2007507E:BIO routines:MEM_WRITE:write to read only
BIO:bss_mem.c:187:
139988672657152:error:2007507E:BIO routines:MEM_WRITE:write to read only
BIO:bss_mem.c:187:
139988672657152:error:2007507E:BIO routines:MEM_WRITE:write to read only
BIO:bss_mem.c:187:
139988672657152:error:2007507E:BIO routines:MEM_WRITE:write to read only
BIO:bss_mem.c:187:
139988672657152:error:2007507E:BIO routines:MEM_WRITE:write to read only
BIO:bss_mem.c:187:
139988672657152:error:2007507E:BIO routines:MEM_WRITE:write to read only
BIO:bss_mem.c:187:
139988672657152:error:2007507E:BIO routines:MEM_WRITE:write to read only
BIO:bss_mem.c:187:
139988672657152:error:2007507E:BIO routines:MEM_WRITE:write to read only
BIO:bss_mem.c:187:
139988672657152:error:2007507E:BIO routines:MEM_WRITE:write to read only
BIO:bss_mem.c:187:
----
And the output file (info_file_p7) is truncated:
----
MIME-Version: 1.0
Content-Type: multipart/signed; protocol="application/pkcs7-signature";
micalg="sha1"; boundary="----5FE1D5622FD3DD8F5A52BBDAB7FFC85C"
This is an S/MIME signed message
------5FE1D5622FD3DD8F5A52BBDAB7FFC85C
Content-Type: text/plain
Extraction by : admin
Generated on : 2011-02-10 14:09:09.076123
Date range : 2011-01-31 23:00:00 -> 2011-02-28 23:00:00
***
AnalyzerID: 2085134905019507
Signature Status: OK
Source : /var/log/messages
Extracted File : 2085134905019507/-var-log-messages
Hash :
{SHA256}0a795db99026b4df1cf73ae656e2cdcfd63242966cca8f6ddc7131d513595ffb
----
The smime.p7m attachment is missing, it is something like:
----
MIME-Version: 1.0
Content-Disposition: attachment; filename="smime.p7m"
Content-Type: application/pkcs7-mime; smime-type=signed-data;
name="smime.p7m"
Content-Transfer-Encoding: base64
MIIIHAYJKoZIhvcNAQcCoIIIDTCCCAkCAQExCzAJBgUrDgMCGgUAMIIBrgYJKoZI
hvcNAQcBoIIBnwSCAZtDb250ZW50LVR5cGU6IHRleHQvcGxhaW4NCg0KRXh0cmFj
dGlvbiBieSA6IGFkbWluDQpHZW5lcmF0ZWQgb24gIDogMjAxMS0wMi0xMCAxNDow
OTowOS4wNzYxMjMNCkRhdGUgcmFuZ2UgICAgOiAyMDExLTAxLTMxIDIzOjAwOjAw
----
It's because the buffer is set to read only mode just after writing the
first part.
Victor
from __future__ import with_statement
from M2Crypto import RSA, BIO, Rand, SMIME, X509
import M2Crypto
from cStringIO import StringIO
import ctypes
with open('infos.txt', 'rb') as input_file:
f = input_file.read()
buf = BIO.MemoryBuffer(f)
print "1 Error ?:", M2Crypto.Err.get_error()
s = SMIME.SMIME()
print "2 Error ?:", M2Crypto.Err.get_error()
s.load_key('prelude-key.pem', 'prelude-cert.pem')
print "3 Error ?:", M2Crypto.Err.get_error()
p7 = s.sign(buf, flags=SMIME.PKCS7_TEXT)
print "4 Error ?:", M2Crypto.Err.get_error()
buf = BIO.MemoryBuffer(f)
out = BIO.MemoryBuffer()
print "5 Error ?:", M2Crypto.Err.get_error()
s.write(out, p7, buf, SMIME.PKCS7_TEXT)
print "6 Error ?:", M2Crypto.Err.get_error()
b = open('infos_file_p7', 'wb')
b.write(out.read_all())
b.close()