Hi Andy,
You where right about the version 0.9.3(a).
I made the following relevant modifications:
- changed the sign.c/verify.c and enc.c/dec.c to be functions
callable by a program. (I also made a small testprogram
calling these functions.)
- modified the 'envelopedData' handling as it didn't comply with
the S/MIME specification.
- tested to change (bigger) the read buffer size in 'dec' to see if this
would decrease the time, but without luck (it's 100K in the example).
- Finally I also changed the input/output format from PEM to DER, as this
is what we want in the calling application.
I also tried to dig down in the decryption code but gave up, )its really
magic). So if you have any idea where to look I would be very greatful.
Thanks for your support.
/Bo
Code extracts from dec:
------dec start--------
int dec_verify_callback(int ok, X509_STORE_CTX *ctx);
BIO *dec_bio_err=NULL;
int dtc_dec(char *encFile, char *docFile, char* certFile, char *keyFile, char* caFile){
BIO *in = NULL;
FILE *out = NULL;
EVP_PKEY *pkey;
X509 *x509;
PKCS7 *p7 = NULL;
PKCS7_SIGNER_INFO *si;
X509_STORE_CTX cert_ctx;
X509_STORE *cert_store=NULL;
BIO *data = NULL,*detached=NULL,*p7bio=NULL;
char buf[102400*4];
int i,printit=0;
STACK *sk;
SSLeay_add_all_algorithms();
dec_bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
data=BIO_new(BIO_s_file());
if (!BIO_read_filename(data, encFile)) goto err;
if ((out = fopen(docFile,"w")) == NULL) goto err;
if ((in=BIO_new_file(certFile,"r")) == NULL) goto err;
if ((x509=PEM_read_bio_X509(in,NULL,NULL)) == NULL) goto err;
BIO_free(in);
in = NULL;
if ((in=BIO_new_file(keyFile,"r")) == NULL) goto err;
if ((pkey=PEM_read_bio_PrivateKey(in,NULL,NULL)) == NULL) goto err;
BIO_free(in);
in = NULL;
/* Load the PKCS7 object from a file */
if ((p7=d2i_PKCS7_bio(data,NULL)) == NULL) goto err;
/* This stuff is being setup for certificate verification.
* When using SSL, it could be replaced with a
* cert_stre=SSL_CTX_get_cert_store(ssl_ctx); */
cert_store=X509_STORE_new();
X509_STORE_set_default_paths(cert_store);
X509_STORE_load_locations(cert_store, caFile, NULL);
X509_STORE_set_verify_cb_func(cert_store,dec_verify_callback);
ERR_clear_error();
/* We need to process the data */
/* We cannot support detached encryption */
p7bio=PKCS7_dataDecode(p7,pkey,detached,x509);
if (p7bio == NULL)
{
printf("problems decoding\n");
goto err;
}
/* We now have to 'read' from p7bio to calculate digests etc. */
for (;;)
{
i=BIO_read(p7bio,buf,sizeof(buf));
/* print it? */
if (i <= 0) break;
fwrite(buf,1, i, out);
}
/* We can now verify signatures */
sk=PKCS7_get_signer_info(p7);
if (sk != NULL)
{
/* Ok, first we need to, for each subject entry,
* see if we can verify */
ERR_clear_error();
for (i=0; i<sk_num(sk); i++)
{
si=(PKCS7_SIGNER_INFO *)sk_value(sk,i);
i=PKCS7_dataVerify(cert_store,&cert_ctx,p7bio,p7,si);
if (i <= 0)
goto err;
else
fprintf(stderr,"Signature verified\n");
}
}
X509_STORE_free(cert_store);
/*
PKCS7_free(p7);
*/
BIO_free(data);
BIO_free(p7bio);
fclose(out);
return(0);
err:
ERR_load_crypto_strings();
ERR_print_errors_fp(stderr);
if(cert_store != NULL) X509_STORE_free(cert_store);
/*
if(p7 != NULL) PKCS7_free(p7);
*/
if(in != NULL) BIO_free(in);
if(data != NULL) BIO_free(data);
if(p7bio != NULL) BIO_free(p7bio);
if(out != NULL) fclose(out);
return(1);
}
/* should be X509 * but we can just have them as char *. */
int dec_verify_callback(int ok, X509_STORE_CTX *ctx)
{
char buf[256];
X509 *err_cert;
int err,depth;
err_cert=X509_STORE_CTX_get_current_cert(ctx);
err= X509_STORE_CTX_get_error(ctx);
depth= X509_STORE_CTX_get_error_depth(ctx);
X509_NAME_oneline(X509_get_subject_name(err_cert),buf,256);
BIO_printf(dec_bio_err,"depth=%d %s\n",depth,buf);
if (!ok)
{
BIO_printf(dec_bio_err,"verify error:num=%d:%s\n",err,
X509_verify_cert_error_string(err));
if (depth < 6)
{
ok=1;
X509_STORE_CTX_set_error(ctx,X509_V_OK);
}
else
{
ok=0;
X509_STORE_CTX_set_error(ctx,X509_V_ERR_CERT_CHAIN_TOO_LONG);
}
}
switch (ctx->error)
{
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256);
BIO_printf(dec_bio_err,"issuer= %s\n",buf);
break;
case X509_V_ERR_CERT_NOT_YET_VALID:
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
BIO_printf(dec_bio_err,"notBefore=");
ASN1_UTCTIME_print(dec_bio_err,X509_get_notBefore(ctx->current_cert));
BIO_printf(dec_bio_err,"\n");
break;
case X509_V_ERR_CERT_HAS_EXPIRED:
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
BIO_printf(dec_bio_err,"notAfter=");
ASN1_UTCTIME_print(dec_bio_err,X509_get_notAfter(ctx->current_cert));
BIO_printf(dec_bio_err,"\n");
break;
}
BIO_printf(dec_bio_err,"verify return:%d\n",ok);
return(ok);
}
------START end--------
------START pkcs7 related ASN.1 code (from /crypto/asn1: p7_enc_c.c ,p7_evp.c and
p7_lib.c )-----
/* it is this function that is changed the other ASN.1 related functions below is just
to make the
call to this function using the 'dtc_' prefix. (I havent changed the original
functions, but added
this as 'my own' overriding the original openssl code.*/
int dtc_i2d_PKCS7_ENC_CONTENT(PKCS7_ENC_CONTENT *a, unsigned char **pp)
{
M_ASN1_I2D_vars(a);
M_ASN1_I2D_len(a->content_type,i2d_ASN1_OBJECT);
M_ASN1_I2D_len(a->algorithm,i2d_X509_ALGOR);
/* dtc compensation for INF SEQ in ENC_CONTENT */
ret += 4;
/* dtc_ M_ASN1_I2D_len_IMP_opt(a->enc_data,i2d_ASN1_OCTET_STRING);
* is replaced by: */
M_ASN1_I2D_len(a->enc_data,i2d_ASN1_OCTET_STRING);
M_ASN1_I2D_seq_total();
/* dtc_ changed due to the fact that Netscape Messenger and
* WorldSecure are using 'data' instead of 'encryptedData' */
a->content_type->data[8] = OBJ_pkcs7_data;
M_ASN1_I2D_put(a->content_type,i2d_ASN1_OBJECT);
/* dtc_ Restoring it to avoid problems */
a->content_type->data[8] = OBJ_pkcs7_encrypted;
M_ASN1_I2D_put(a->algorithm,i2d_X509_ALGOR);
M_ASN1_I2D_INF_seq_start(0,V_ASN1_CONTEXT_SPECIFIC);
/* dtc_ M_ASN1_I2D_put_IMP_opt(a->enc_data,i2d_ASN1_OCTET_STRING,0);
* is replaced by: */
M_ASN1_I2D_put(a->enc_data,i2d_ASN1_OCTET_STRING);
M_ASN1_I2D_INF_seq_end();
M_ASN1_I2D_finish();
}
/* From: crypto/asn1/p7_evp.c */
/*
* This function replaces the corresponding i2d_PKCS7_ENVELOPE
* function in the crypto/asn1/p7_evp.c module. It is replaced
* due to a bug in the i2d_PKCS7_ENC_CONTENT part, called below.
*/
int dtc_i2d_PKCS7_ENVELOPE(PKCS7_ENVELOPE *a, unsigned char **pp)
{
M_ASN1_I2D_vars(a);
M_ASN1_I2D_len(a->version,i2d_ASN1_INTEGER);
M_ASN1_I2D_len_SET(a->recipientinfo,i2d_PKCS7_RECIP_INFO);
/* Replaced i2d_PKCS7_ENC_CONTENT */
M_ASN1_I2D_len(a->enc_data,dtc_i2d_PKCS7_ENC_CONTENT);
M_ASN1_I2D_seq_total();
M_ASN1_I2D_put(a->version,i2d_ASN1_INTEGER);
M_ASN1_I2D_put_SET(a->recipientinfo,i2d_PKCS7_RECIP_INFO);
/* Replaced i2d_PKCS7_ENC_CONTENT */
M_ASN1_I2D_put(a->enc_data,dtc_i2d_PKCS7_ENC_CONTENT);
M_ASN1_I2D_finish();
}
/* From: crypto/asn1/p7_lib.c */
/*
* This function replaces the corresponding i2d_PKCS7 function
* in the crypto/asn1/p7_lib.c module. It is replaced due to a
* bug in the i2d_PKCS7_ENC_CONTENT part, which is called by the
* i2d_PKCS7_ENVELOPE below.
*/
int dtc_i2d_PKCS7(PKCS7 *a, unsigned char **pp)
{
M_ASN1_I2D_vars(a);
if (a->asn1 != NULL)
{
if (pp == NULL)
return((int)a->length);
memcpy(*pp,a->asn1,(int)a->length);
*pp+=a->length;
return((int)a->length);
}
ret+=4; /* sequence, BER header plus '0 0' end padding */
M_ASN1_I2D_len(a->type,i2d_ASN1_OBJECT);
if (a->d.ptr != NULL)
{
ret+=4; /* explicit tag [ 0 ] BER plus '0 0' */
switch (OBJ_obj2nid(a->type))
{
case NID_pkcs7_data:
M_ASN1_I2D_len(a->d.data,i2d_ASN1_OCTET_STRING);
break;
case NID_pkcs7_signed:
M_ASN1_I2D_len(a->d.sign,i2d_PKCS7_SIGNED);
break;
case NID_pkcs7_enveloped:
/* Replaced i2d_PKCS7_ENVELOPE */
M_ASN1_I2D_len(a->d.enveloped,dtc_i2d_PKCS7_ENVELOPE);
break;
case NID_pkcs7_signedAndEnveloped:
M_ASN1_I2D_len(a->d.signed_and_enveloped,
i2d_PKCS7_SIGN_ENVELOPE);
break;
case NID_pkcs7_digest:
M_ASN1_I2D_len(a->d.digest,i2d_PKCS7_DIGEST);
break;
case NID_pkcs7_encrypted:
M_ASN1_I2D_len(a->d.encrypted,i2d_PKCS7_ENCRYPT);
break;
default:
break;
}
}
r=ret;
if (pp == NULL) return(r);
p= *pp;
M_ASN1_I2D_INF_seq_start(V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
M_ASN1_I2D_put(a->type,i2d_ASN1_OBJECT);
if (a->d.ptr != NULL)
{
M_ASN1_I2D_INF_seq_start(0,V_ASN1_CONTEXT_SPECIFIC);
switch (OBJ_obj2nid(a->type))
{
case NID_pkcs7_data:
M_ASN1_I2D_put(a->d.data,i2d_ASN1_OCTET_STRING);
break;
case NID_pkcs7_signed:
M_ASN1_I2D_put(a->d.sign,i2d_PKCS7_SIGNED);
break;
case NID_pkcs7_enveloped:
/* Replaced i2d_PKCS7_ENVELOPE */
M_ASN1_I2D_put(a->d.enveloped,dtc_i2d_PKCS7_ENVELOPE);
break;
case NID_pkcs7_signedAndEnveloped:
M_ASN1_I2D_put(a->d.signed_and_enveloped,
i2d_PKCS7_SIGN_ENVELOPE);
break;
case NID_pkcs7_digest:
M_ASN1_I2D_put(a->d.digest,i2d_PKCS7_DIGEST);
break;
case NID_pkcs7_encrypted:
M_ASN1_I2D_put(a->d.encrypted,i2d_PKCS7_ENCRYPT);
break;
default:
break;
}
M_ASN1_I2D_INF_seq_end();
}
M_ASN1_I2D_INF_seq_end();
M_ASN1_I2D_finish();
}
---- END pkcs7 ASN.1 related code------
----- Ursprungligt meddelande -----
Från: Andy Polyakov <[EMAIL PROTECTED]>
Till: <[EMAIL PROTECTED]>
Skickat: den 13 augusti 1999 15:35
Ämne: Re: Performance
> > >> I am using a partly modified PKCS7 enc.c and dec.c for
> > >> encrypting and decrypting documents.
> > >> When encrypting an 8,5MB file it takes about 1 minute,
> > >> however when decrypting it the time runs up to 20 minutes.
> > >Which platform? Which compiler? What does './config -t' say?
> > './config -t' says:
> > Operating system: sun4u-sun-solaris2
> > gcc version egcs-2.90.x
> > Configuring for solaris-usparc-oldgcc
> I managed to reproduce it on 0.9.3[a] as this's what you must have. This
> -oldgcc thing was fixed and usparc was changed to sparcv9 in 0.9.4. I
> experience much bigger differences in execution times. I managed to
> ./crypto/pkc7/enc 12MB file in 8 seconds, while dec took over 8 minutes.
> You mentioned it was "partly modified". Can you post your code? If it's
> big, then post it to me, I'll summarize. Did you try it with 0.9.4? I
> didn't manage to compile ./crypto/pkc7/[enc|dec].c just yet...
>
> Andy.
> ______________________________________________________________________
> OpenSSL Project http://www.openssl.org
> Development Mailing List [EMAIL PROTECTED]
> Automated List Manager [EMAIL PROTECTED]
>
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [EMAIL PROTECTED]
Automated List Manager [EMAIL PROTECTED]