aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/smime.c28
-rw-r--r--crypto/pkcs7/pk7_smime.c23
-rw-r--r--crypto/pkcs7/pkcs7.h1
-rw-r--r--crypto/pkcs7/pkcs7err.c1
-rw-r--r--doc/man/smime.pod241
5 files changed, 284 insertions, 10 deletions
diff --git a/apps/smime.c b/apps/smime.c
index 0d713a52b5..f87b41969d 100644
--- a/apps/smime.c
+++ b/apps/smime.c
@@ -136,6 +136,8 @@ int MAIN(int argc, char **argv)
flags &= ~PKCS7_DETACHED;
else if (!strcmp (*args, "-binary"))
flags |= PKCS7_BINARY;
+ else if (!strcmp (*args, "-nosigs"))
+ flags |= PKCS7_NOSIGS;
else if (!strcmp (*args, "-to")) {
if (args[1]) {
args++;
@@ -224,6 +226,13 @@ int MAIN(int argc, char **argv)
BIO_printf (bio_err, "-rc2-40 encrypt with RC2-40\n");
BIO_printf (bio_err, "-rc2-64 encrypt with RC2-64\n");
BIO_printf (bio_err, "-rc2-128 encrypt with RC2-128\n");
+ BIO_printf (bio_err, "-nointern don't search certificates in message for signer\n");
+ BIO_printf (bio_err, "-nosigs don't verify message signature\n");
+ BIO_printf (bio_err, "-noverify don't verify signers certificate\n");
+ BIO_printf (bio_err, "-nocerts don't include signers certificate when signing\n");
+ BIO_printf (bio_err, "-nodetach use opaque signing\n");
+ BIO_printf (bio_err, "-noattr don't include any signed attributes\n");
+ BIO_printf (bio_err, "-binary don't translate message to text\n");
BIO_printf (bio_err, "-in file input file\n");
BIO_printf (bio_err, "-certfile file other certificates file\n");
BIO_printf (bio_err, "-signer file signer certificate file\n");
@@ -235,6 +244,8 @@ int MAIN(int argc, char **argv)
BIO_printf (bio_err, "-from ad from address\n");
BIO_printf (bio_err, "-subject s subject\n");
BIO_printf (bio_err, "-text include or delete text MIME headers\n");
+ BIO_printf (bio_err, "-CApath dir trusted certificates directory\n");
+ BIO_printf (bio_err, "-CAfile file trusted certificates file\n");
BIO_printf (bio_err, "cert.pem recipient certificate(s)\n");
goto end;
}
@@ -319,6 +330,7 @@ int MAIN(int argc, char **argv)
if(!(store = setup_verify(CAfile, CApath))) goto end;
ret = 3;
+
if(operation == SMIME_ENCRYPT) {
p7 = PKCS7_encrypt(encerts, in, cipher, flags);
} else if(operation == SMIME_SIGN) {
@@ -327,34 +339,35 @@ int MAIN(int argc, char **argv)
} else {
if(!(p7 = SMIME_read_PKCS7(in, &indata))) {
BIO_printf(bio_err, "Error reading S/MIME message\n");
- ret = 4;
goto end;
}
}
-
+
if(!p7) {
BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
goto end;
}
+ ret = 4;
if(operation == SMIME_DECRYPT) {
- if(!PKCS7_decrypt(p7, key, recip, out, flags))
+ if(!PKCS7_decrypt(p7, key, recip, out, flags)) {
BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
- else ret = 0;
+ goto end;
+ }
} else if(operation == SMIME_VERIFY) {
STACK_OF(X509) *signers;
signers = PKCS7_iget_signers(p7, other, flags);
if(PKCS7_verify(p7, other, store, indata, out, flags)) {
BIO_printf(bio_err, "Verification Successful\n");
- ret = 0;
} else {
BIO_printf(bio_err, "Verification Failure\n");
- ret = 5;
+ goto end;
}
if(!save_certs(signerfile, signers)) {
BIO_printf(bio_err, "Error writing signers to %s\n",
signerfile);
- ret = 2;
+ ret = 5;
+ goto end;
}
sk_X509_free(signers);
} else if(operation == SMIME_PK7OUT) {
@@ -365,6 +378,7 @@ int MAIN(int argc, char **argv)
if(subject) BIO_printf(out, "Subject: %s\n", subject);
SMIME_write_PKCS7(out, p7, in, flags);
}
+ ret = 0;
end:
if(ret) ERR_print_errors(bio_err);
sk_X509_pop_free(encerts, X509_free);
diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c
index 3f6cad44f8..4b557f48a2 100644
--- a/crypto/pkcs7/pk7_smime.c
+++ b/crypto/pkcs7/pk7_smime.c
@@ -150,14 +150,19 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
BIO *p7bio;
BIO *tmpout;
+ if(!p7) {
+ PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_INVALID_NULL_POINTER);
+ return NULL;
+ }
+
if(!PKCS7_type_is_signed(p7)) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_WRONG_CONTENT_TYPE);
+ PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
/* Check for no data and no content: no data to verify signature */
if(PKCS7_get_detached(p7) && !indata) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_CONTENT);
+ PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_CONTENT);
return 0;
}
@@ -170,7 +175,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
sinfos = PKCS7_get_signer_info(p7);
if(!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_SIGNATURES_ON_DATA);
+ PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_SIGNATURES_ON_DATA);
return 0;
}
@@ -264,6 +269,11 @@ STACK_OF(X509) *PKCS7_iget_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags)
X509 *signer;
int i;
+ if(!p7) {
+ PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,PKCS7_R_INVALID_NULL_POINTER);
+ return NULL;
+ }
+
if(!PKCS7_type_is_signed(p7)) {
PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,PKCS7_R_WRONG_CONTENT_TYPE);
return NULL;
@@ -376,10 +386,17 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
BIO *tmpmem;
int ret, i;
char buf[4096];
+
+ if(!p7) {
+ PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_INVALID_NULL_POINTER);
+ return 0;
+ }
+
if(!PKCS7_type_is_enveloped(p7)) {
PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
+
if(!X509_check_private_key(cert, pkey)) {
PKCS7err(PKCS7_F_PKCS7_DECRYPT,
PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
diff --git a/crypto/pkcs7/pkcs7.h b/crypto/pkcs7/pkcs7.h
index 7369e324d7..63a97e1540 100644
--- a/crypto/pkcs7/pkcs7.h
+++ b/crypto/pkcs7/pkcs7.h
@@ -455,6 +455,7 @@ int SMIME_text(BIO *in, BIO *out);
#define PKCS7_R_ERROR_SETTING_CIPHER 121
#define PKCS7_R_INTERNAL_ERROR 102
#define PKCS7_R_INVALID_MIME_TYPE 131
+#define PKCS7_R_INVALID_NULL_POINTER 143
#define PKCS7_R_MIME_NO_CONTENT_TYPE 132
#define PKCS7_R_MIME_PARSE_ERROR 133
#define PKCS7_R_MIME_SIG_PARSE_ERROR 134
diff --git a/crypto/pkcs7/pkcs7err.c b/crypto/pkcs7/pkcs7err.c
index d0a1f599ab..d8491ff71b 100644
--- a/crypto/pkcs7/pkcs7err.c
+++ b/crypto/pkcs7/pkcs7err.c
@@ -105,6 +105,7 @@ static ERR_STRING_DATA PKCS7_str_reasons[]=
{PKCS7_R_ERROR_SETTING_CIPHER ,"error setting cipher"},
{PKCS7_R_INTERNAL_ERROR ,"internal error"},
{PKCS7_R_INVALID_MIME_TYPE ,"invalid mime type"},
+{PKCS7_R_INVALID_NULL_POINTER ,"invalid null pointer"},
{PKCS7_R_MIME_NO_CONTENT_TYPE ,"mime no content type"},
{PKCS7_R_MIME_PARSE_ERROR ,"mime parse error"},
{PKCS7_R_MIME_SIG_PARSE_ERROR ,"mime sig parse error"},
diff --git a/doc/man/smime.pod b/doc/man/smime.pod
new file mode 100644
index 0000000000..6ec5640370
--- /dev/null
+++ b/doc/man/smime.pod
@@ -0,0 +1,241 @@
+=pod
+
+=head1 NAME
+
+smime - S/MIME utility
+
+=head1 SYNOPSIS
+
+B<openssl> B<smime>
+[B<-encrypt>]
+[B<-decrypt>]
+[B<-sign>]
+[B<-verify>]
+[B<-pk7out>]
+[B<-des3>]
+[B<-rc2-40>]
+[B<-rc2-64>]
+[B<-rc2-128>]
+[B<-in file>]
+[B<-certfile file>]
+[B<-signer file>]
+[B<-recip file>]
+[B<-in file>]
+[B<-inkey file>]
+[B<-out file>]
+[B<-to addr>]
+[B<-from ad>]
+[B<-subject s>]
+[B<-text>]
+[cert.pem]...
+
+=head1 DESCRIPTION
+
+The B<smime> command handles S/MIME mail. It can encrypt, decrypt, sign and
+verify S/MIME messages.
+
+=head1 COMMAND OPTIONS
+
+There are five operation options that set the type of operation to be performed.
+The meaning of the other options varies according to the operation type.
+
+=over 4
+
+=item B<-encrypt>
+
+encrypt mail for the given recipient certificates. Input file is the message
+to be encrypted. The output file is the encrypted mail in MIME format.
+
+=item B<-decrypt>
+
+decrypt mail using the supplied certificate and private key. Expects an
+encrypted mail message in MIME format for the input file. The decrypted mail
+is written to the output file.
+
+=item B<-sign>
+
+sign mail using the supplied certificate and private key. Input file is
+the message to be signed. The signed message in MIME format is written
+to the output file.
+
+=item B<-verify>
+
+verify signed mail. Expects a signed mail message on input and outputs
+the signed data. Both clear text and opaque signing is supported.
+
+=item B<-pk7out>
+
+takes an input message and writes out a PEM encoded PKCS#7 structure.
+
+=item B<-in filename>
+
+the input message to be encrypted or signed or the MIME message to
+be decrypted or verified.
+
+=item B<-out filename>
+
+the message text that has been decrypted or verified or the output MIME
+format message that has been signed or verified.
+
+=item B<-text>
+
+this option adds plain text (text/plain) MIME headers to the supplied
+message if encrypting or signing. If decrypting or verifying it strips
+off text headers: if the decrypted or verified message is not of MIME
+type text/plain then an error occurs.
+
+=item B<-CAfile file>
+
+a file containing trusted CA certificates, only used with B<-verify>.
+
+=item B<-CApath dir>
+
+a directory containing trusted CA certificates, only used with
+B<-verify>. This directory must be a standard certificate directory: that
+is a hash of each subject name (using B<x509 -hash>) should be linked
+to each certificate.
+
+=item B<-des3 -rc2-40 -rc2-64 -rc2-128>
+
+the encryption algorithm to use. DES (56 bits), triple DES (168 bits)
+or 40, 64 or 128 bit RC2 respectively if not specified 40 bit RC2 is
+used. Only used with B<-encrypt>.
+
+=item B<-nointern>
+
+when verifying a message normally certificates (if any) included in
+the message are searched for the signing certificate. With this option
+only the certificates specified in the B<-certfile> option are used.
+The supplied certificates can still be used as untrusted CAs however.
+
+=item B<-noverify>
+
+do not verify the signers certificate of a signed message.
+
+=item B<-nochain>
+
+do not do chain verification of signers certfificates: that is don't
+use the certificates in the signed message as untrusted CAs.
+
+=item B<-nosigs>
+
+don't try to verify the signatures on the message.
+
+=item B<-nocerts>
+
+when signing a message the signer's certificate is normally included
+with this option it is excluded. This will reduce the size of the
+signed message but the verifier must have a copy of the signers certificate
+available locally (passed using the B<-certfile> option for example).
+
+=item B<-noattr>
+
+normally when a message is signed a set of attributes are included which
+include the signing time and supported symmetric algorithms. With this
+option they are not included.
+
+=item B<-binary>
+
+normally the input message is converted to "canonical" format which is
+effectively using CR and LF as end of line. When this option is present
+no translation occurs. This is useful when handling binary data which may
+not be in MIME format.
+
+=item B<-nodetach>
+
+when signing a message use opaque signing: this form is more resistant
+to translation by mail relays but it cannot be read by mail agents that
+do not support S/MIME. Without this option cleartext signing with
+the MIME type multipart/signed is used.
+
+=item B<-certfile file>
+
+allows additional certificates to be specified. When signing these will
+be included with the message. When verifying these will be searched for
+the signers certificates. The certificates should be in PEM format.
+
+=item B<-signer file>
+
+the signers certificate when signing a message. If a message is
+being verified then the signers certificates will be written to this
+file if the verification was successful.
+
+=item B<-recip file>
+
+the recipients certificate when decrypting a message. This certificate
+must match one of the recipients of the message or an error occurs.
+
+=item B<-inkey file>
+
+the private key to use when signing or decrypting. This must match the
+corresponding certificate. If this option is not specified then the
+private key must be included in the certificate file specified with
+the B<-recip> or B<-signer> file.
+
+=item B<cert.pem...>
+
+one or more certificates of message recipients: used when encrypting
+a message.
+
+=item B<-to, -from, -subject>
+
+the relevant mail headers. These are included outside the signed
+portion of a message so they may be included manually. If signing
+then many S/MIME mail clients check the signers certificate's email
+address matches that specified in the From: address.
+
+=back
+
+=head1 NOTES
+
+The MIME message must be sent without any blank lines between the
+headers and the output. Some mail programs will automatically add
+a blank line. Piping the mail directly to sendmail is one way to
+achieve the correct format.
+
+A "signed and encrypted" message is one where a signed message is
+then encrypted. This can be produced by encrypting an already signed
+message.
+
+This version of the program only allows one signer per message but it
+will verify multiple signers on received messages. Some S/MIME clients
+choke if a message contains mutiple signers. It is possible to sign
+messages "in parallel" by signing an already signed message.
+
+=head1 EXIT CODES
+
+=over 4
+
+=item 0
+
+the operation was completely successful
+
+=item 1
+
+an error occurred parsing the command options.
+
+=item 2
+
+one of the input files could not be read.
+
+=item 3
+
+an error occurred creating the PKCS#7 file or when reading the MIME
+message.
+
+=item 4
+
+an error occurred decrypting or verifying the message.
+
+=item 5
+
+the message was verified correctly but an error occured writing out
+the signers certificates.
+
+=back
+
+=head1 EXAMPLES
+
+to be added.
+
+=cut