1 /* smime-vfy.c  -  Utility functions for performing S/MIME signature
2  *                 verification and decryption.
3  *
4  * Copyright (c) 1999 Sampo Kellomaki <sampo@iki.fi>, All Rights Reserved.
5  * License: This software may be distributed under the same license
6  *          terms as openssl (i.e. free, but mandatory attribution).
7  *          See file LICENSE for details.
8  *
9  * 11.9.1999,  Created. --Sampo
10  * 13.9.1999,  0.1 released. Now adding verify. --Sampo
11  * 1.10.1999,  improved error handling, fixed decrypt --Sampo
12  * 6.10.1999,  separated from smimeutil.c --Sampo
13  * 9.10.1999,  fixed double free in decryption --Sampo
14  * 14.11.1999, added verification of detached sigs, i.e. clear sigs --Sampo
15  *
16  * This module has adopted ideas and control flow from
17  *    openssl-0.9.4/crypto/pkcs7/sign.c
18  *    openssl-0.9.4/crypto/pkcs7/verify.c
19  *    openssl-0.9.4/crypto/pkcs7/enc.c
20  *    openssl-0.9.4/crypto/pkcs7/dec.c
21  * which are Copyright (c) 1995-1998 Eric Young (eay@cryptsoft.com),
22  * All rights reserved. See file LICENSE for conditions.
23  *
24  * This module has been developed to support a Lingo XTRA that is supposed
25  * to provide crypto functionality. It may, however, be useful for other
26  * purposes as well.
27  *
28  * This is a very simple S/MIME library. For example the multipart
29  * boundary separators are hard coded and no effort is made to verify
30  * that mime entities are in their canonical form before signing (the
31  * caller should make sure they are, canonical form means using CRLF
32  * as line termination, among other things). Also the multipart functionality
33  * only understands up to 3 attachments. For many tasks this is enough,
34  * but if its not, feel free to write more generic utilities.
35  *
36  * Memory management: most routines malloc the results. Freeing them is
37  * application's responsibility. I use libc malloc, but if in doubt
38  * it might be safer to just leak the memory (i.e. don't ever free it).
39  * This library works entirely in memory, so maximum memory consumption
40  * might be more than twice the total size of all files to be encrypted.
41  */
42 
43 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
44  * All rights reserved.
45  *
46  * This package is an SSL implementation written
47  * by Eric Young (eay@cryptsoft.com).
48  * The implementation was written so as to conform with Netscapes SSL.
49  *
50  * This library is free for commercial and non-commercial use as long as
51  * the following conditions are aheared to.  The following conditions
52  * apply to all code found in this distribution, be it the RC4, RSA,
53  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
54  * included with this distribution is covered by the same copyright terms
55  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
56  *
57  * Copyright remains Eric Young's, and as such any Copyright notices in
58  * the code are not to be removed.
59  * If this package is used in a product, Eric Young should be given attribution
60  * as the author of the parts of the library used.
61  * This can be in the form of a textual message at program startup or
62  * in documentation (online or textual) provided with the package.
63  *
64  * Redistribution and use in source and binary forms, with or without
65  * modification, are permitted provided that the following conditions
66  * are met:
67  * 1. Redistributions of source code must retain the copyright
68  *    notice, this list of conditions and the following disclaimer.
69  * 2. Redistributions in binary form must reproduce the above copyright
70  *    notice, this list of conditions and the following disclaimer in the
71  *    documentation and/or other materials provided with the distribution.
72  * 3. All advertising materials mentioning features or use of this software
73  *    must display the following acknowledgement:
74  *    "This product includes cryptographic software written by
75  *     Eric Young (eay@cryptsoft.com)"
76  *    The word 'cryptographic' can be left out if the rouines from the library
77  *    being used are not cryptographic related :-).
78  * 4. If you include any Windows specific code (or a derivative thereof) from
79  *   the apps directory (application code) you must include an acknowledgement:
80  *   "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
81  *
82  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
83  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
84  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
85  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
86  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
87  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
88  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
89  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
90  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
91  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
92  * SUCH DAMAGE.
93  *
94  * The licence and distribution terms for any publically available version or
95  * derivative of this code cannot be changed.  i.e. this code cannot simply be
96  * copied and put under another distribution licence
97  * [including the GNU Public Licence.]
98  */
99 
100 #include "platform.h"
101 
102 #include <stdlib.h>
103 #include <string.h>
104 #include <time.h>
105 
106 #if defined(macintosh) || defined(__INTEL__)
107 #include "macglue.h"
108 #endif
109 
110 #include "logprint.h"
111 
112 #include <openssl/crypto.h>
113 #include <openssl/buffer.h>
114 #include <openssl/stack.h>
115 #include <openssl/bio.h>
116 #include <openssl/x509.h>
117 #include <openssl/pem.h>
118 #include <openssl/err.h>
119 
120 #define SMIME_INTERNALS  /* we want also our internal helper functions */
121 #include "smimeutil.h"
122 
123 /* ============= S I G N A T U R E   V E R I F I C A T I O N ============== */
124 /* ==================== A N D   D E C R Y P T I O N ======================= */
125 
126 /* Called by:  decrypt, smime_get_signer_info, smime_verify_signature */
127 static PKCS7*
get_pkcs7_from_pem(const char * enc_entity)128 get_pkcs7_from_pem(const char* enc_entity)
129 {
130   const char* p;
131   char*  wrapped_enc_entity = NULL;
132   BIO*   rbio = NULL;
133   PKCS7* p7 = NULL;
134 
135   /* Check if encrypted entity is composed of raw data or if it has some
136    * headers. In the latter case, just skip the headers. Headers are
137    * separated from data by an empty line (hence sequence CRLF CRLF).*/
138 
139   if ((p = strstr(enc_entity, CRLF CRLF))) {
140     enc_entity = p+4;
141   } else if ((p = strstr(enc_entity, LF LF))) {
142     enc_entity = p+2;
143   } else if ((p = strstr(enc_entity, CR CR))) {
144     enc_entity = p+2;
145   }
146 
147   /* Make sure the pem markers are there */
148 
149   LOG_PRINT("get_pkcs7_from_pem: wrapping in pem markers");
150 
151   if (!(wrapped_enc_entity = wrap_in_pem_markers(enc_entity, "PKCS7")))
152     GOTO_ERR("no memory?");
153   LOG_PRINT("get_pkcs7_from_pem: wrapped.");
154 
155   /* Set up BIO so encrypted/signed data can be read from pem file */
156 
157   if (!(rbio = set_read_BIO_from_buf(wrapped_enc_entity, -1))) goto err;
158 
159   LOG_PRINT("get_pkcs7_from_pem: ready to read PKCS7 bio...");
160 
161   /* Load the PKCS7 object from a pem file to internal representation.
162    * this reads all of the data file. */
163 
164   if (!(p7=PEM_read_bio_PKCS7(rbio,NULL/*&x*/,NULL/*callback*/,NULL/*arg*/)))
165     GOTO_ERR("11 corrupt PEM PKCS7 file? (PEM_read_bio_PKCS7)");
166 
167   LOG_PRINT("get_pkcs7_from_pem: bio read");
168 
169   BIO_free_all(rbio);
170   OPENSSL_free(wrapped_enc_entity);
171   return p7;
172 err:
173   if (rbio) BIO_free_all(rbio);
174   if (wrapped_enc_entity) OPENSSL_free(wrapped_enc_entity);
175   return NULL;
176 }
177 
178 /* Typically receiver has to know in what order the signature and encryption
179  * were applied (usually encryption is outermost) and then call these
180  * functions in right order, e.g:
181  */
182 
183 /* Called by:  smime_decrypt */
184 int  /* return size of data, -1 on failure */
decrypt(X509 * x509,EVP_PKEY * pkey,const char * enc_entity,char ** data_out)185 decrypt(X509* x509, EVP_PKEY* pkey, const char* enc_entity, char** data_out)
186 {
187   char buf[4096];
188   int  i,n;
189   BIO* wbio = NULL;
190   BIO* p7bio = NULL;
191   PKCS7 *p7 = NULL;
192 
193   if (data_out) *data_out = NULL;
194   if (!x509 || !pkey || !enc_entity || !data_out) GOTO_ERR("NULL arg(s)");
195   LOG_PRINT("decrypt: get_pkcs7_from_pem");
196   if (!(p7 = get_pkcs7_from_pem(enc_entity))) goto err;
197 
198   /* Decrypt the symmetric key with private key and obtain symmetric
199    * cipher stream (BIO). The cert is needed here to look up one of
200    * possibly multiple recipient infos present in PKCS7 object. Issuer
201    * and serial number must match (these two fields form unique ID for
202    * cert). Actual public key part of the X509 cert is not used for
203    * anything here.  */
204 
205   LOG_PRINT("decrypt: dataDecode");
206   if (!(p7bio=PKCS7_dataDecode(p7,pkey,NULL/*detached*/,x509)))
207     GOTO_ERR("12 no recipient matches cert or private key could not decrypt, i.e. wrong key (PKCS7_dataDecode)");
208   LOG_PRINT("decrypt: ready to pump");
209 
210   /* Pump data from p7bio to decrypt symmetric cipher */
211 
212   if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
213 
214   for (;;) {
215     if ((i=BIO_read(p7bio,buf,sizeof(buf))) <= 0) break;
216     BIO_write(wbio,buf,i);
217   }
218   BIO_flush(wbio);
219   BIO_free_all(p7bio);
220   p7bio = NULL;
221   PKCS7_free(p7);
222   p7 = NULL;
223 
224   LOG_PRINT("decrypt: pump done");
225 
226   /* Return data (this should now be easier because we just freed
227    * some memory) */
228 
229   n = get_written_BIO_data(wbio, data_out);
230   BIO_free_all(wbio);
231   return n;
232 
233 err:
234   if (p7)    PKCS7_free(p7);
235   if (wbio)  BIO_free_all(wbio);
236   if (p7bio) BIO_free_all(p7bio);
237   return -1;
238 }
239 
240 /* Called by:  main */
241 int  /* return size of data, -1 on failure */
smime_decrypt(const char * privkey,const char * passwd,const char * enc_entity,char ** data_out)242 smime_decrypt(const char* privkey,
243 	      const char* passwd,
244 	      const char* enc_entity,
245 	      char** data_out)
246 {
247   int  n = -1;
248   EVP_PKEY *pkey = NULL;
249   X509  *x509 = NULL;
250 
251   if (data_out) *data_out = NULL;
252   if (!privkey || !passwd || !enc_entity || !data_out) GOTO_ERR("NULL arg(s)");
253   if (!(pkey = open_private_key(privkey, passwd))) goto err;
254   if (!(x509 = extract_certificate(privkey)))      goto err;
255   n = decrypt(x509, pkey, enc_entity, data_out);
256 
257 err:
258   if (pkey)  EVP_PKEY_free(pkey);
259   if (x509)  X509_free(x509);
260   return n;
261 }
262 
263 /* ------------------------------------------------ */
264 
265 #if 0
266 /* copied from verify.c */
267 /* should be X509* but we can just have them as char*. (??? --Sampo) */
268 /* Called by: */
269 static int
270 verify_callback(int ok, X509_STORE_CTX *ctx) {
271   char buf[256];
272   X509 *err_cert;
273   int err,depth;
274 
275   err_cert=X509_STORE_CTX_get_current_cert(ctx);
276   err=	 X509_STORE_CTX_get_error(ctx);
277   depth= X509_STORE_CTX_get_error_depth(ctx);
278 
279   X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf));
280   fprintf(stderr,"depth=%d %s\n",depth,buf);
281   if (!ok) {
282     fprintf(stderr,"verify error:num=%d:%s\n",err,
283 	    X509_verify_cert_error_string(err));
284     if (depth < 6) {
285       ok=1;
286       X509_STORE_CTX_set_error(ctx,X509_V_OK);
287     } else {
288       ok=0;
289       X509_STORE_CTX_set_error(ctx,X509_V_ERR_CERT_CHAIN_TOO_LONG);
290     }
291   }
292   switch (ctx->error) {
293   case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
294     X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,sizeof(buf));
295     fprintf(stderr,"issuer= %s\n",buf);
296     break;
297 #if 1
298   case X509_V_ERR_CERT_NOT_YET_VALID:
299   case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
300     fprintf(stderr,"notBefore=");
301     /*ASN1_UTCTIME_print(bio_err,X509_get_notBefore(ctx->current_cert));
302       BIO_printf(bio_err,"\n");*/
303     break;
304   case X509_V_ERR_CERT_HAS_EXPIRED:
305   case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
306     fprintf(stderr,"notAfter=");
307     /*ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ctx->current_cert));
308       BIO_printf(bio_err,"\n"); */
309     break;
310 #endif
311   }
312   fprintf(stderr,"verify return:%d\n",ok);
313   return(ok);
314 }
315 
316 static int signed_seq2string_nid= -1;
317 /* For this case, I will malloc the return strings */
318 /* Called by:  smime_verify_signature */
319 static int
320 get_signed_seq2string(PKCS7_SIGNER_INFO *si, char **str1, char **str2) {
321 #if 0
322   ASN1_TYPE *so;
323   if (signed_seq2string_nid == -1)
324     signed_seq2string_nid=
325       OBJ_create("1.9.9999","OID_example","Our example OID");
326   /* To retrieve */
327   so=PKCS7_get_signed_attribute(si,signed_seq2string_nid);
328   if (so && (so->type == V_ASN1_SEQUENCE))
329     {
330       ASN1_CTX c;
331       ASN1_STRING *s;
332       long length;
333       ASN1_OCTET_STRING *os1,*os2;
334 
335       s=so->value.sequence;
336       c.p=ASN1_STRING_data(s);
337       c.max=c.p+ASN1_STRING_length(s);
338       if (!asn1_GetSequence(&c,&length)) GOTO_ERR("") err;
339       /* Length is the length of the seqence */
340 
341       c.q=c.p;
342       if ((os1=d2i_ASN1_OCTET_STRING(NULL,&c.p,c.slen)) == NULL)
343 	GOTO_ERR("");
344       c.slen-=(c.p-c.q);
345 
346       c.q=c.p;
347       if ((os2=d2i_ASN1_OCTET_STRING(NULL,&c.p,c.slen)) == NULL)
348 	GOTO_ERR("");
349       c.slen-=(c.p-c.q);
350 
351       if (!asn1_Finish(&c)) GOTO_ERR("") err;
352       *str1=Malloc(os1->length+1);
353       *str2=Malloc(os2->length+1);
354       memcpy(*str1,os1->data,os1->length);
355       memcpy(*str2,os2->data,os2->length);
356       (*str1)[os1->length]='\0';
357       (*str2)[os2->length]='\0';
358       ASN1_OCTET_STRING_free(os1);
359       ASN1_OCTET_STRING_free(os2);
360       return(1);
361     }
362  err:
363 #endif
364   return(0);
365 }
366 #endif
367 
368 /* Called by:  main */
369 long  /* return serial on success, -1 on failure */
smime_get_signer_info(const char * signed_entity,int info_ix,char ** issuer)370 smime_get_signer_info(const char* signed_entity,
371 		      int info_ix,     /* 0 = first signer */
372 		      char** issuer)   /* DN of the issuer */
373 {
374   int serial = -1;
375   PKCS7* p7 = NULL;
376   STACK_OF(PKCS7_SIGNER_INFO)* sigs = NULL;
377   PKCS7_SIGNER_INFO* si;
378 
379   if (!signed_entity || !issuer) GOTO_ERR("NULL arg(s)");
380   *issuer = NULL;
381 
382   if (!(p7 = get_pkcs7_from_pem(signed_entity))) goto err;
383   if (!(sigs=PKCS7_get_signer_info(p7)))
384     GOTO_ERR("13 no sigs? (PKCS7_get_signer_info)");
385 
386   if (info_ix >= sk_PKCS7_SIGNER_INFO_num(sigs))
387     GOTO_ERR("No more signers. info_ix too large.");
388 
389   if (!(si=sk_PKCS7_SIGNER_INFO_value(sigs,info_ix)))
390     GOTO_ERR("NULL signer info");
391 
392   *issuer = X509_NAME_oneline(si->issuer_and_serial->issuer, NULL,0);
393   serial = ASN1_INTEGER_get(si->issuer_and_serial->serial);
394 
395 err:
396   if (p7) PKCS7_free(p7);
397   return serial;
398 }
399 
400 /* Called by:  main x3 */
401 char* /* returns contents of the signed message, NULL if error */
smime_verify_signature(const char * pubkey,const char * sig_entity,const char * detached_data,int detached_data_len)402 smime_verify_signature(const char* pubkey,
403 		       const char* sig_entity,     /* signed entity
404 						      or just the sigature */
405 		       const char* detached_data,  /* possibly NULL */
406 		       int detached_data_len)
407 {
408   X509*  x509 = NULL;
409   PKCS7* p7 = NULL;
410   STACK_OF(PKCS7_SIGNER_INFO)* sigs = NULL;
411   X509_STORE* certs=NULL;
412   BIO*   detached = NULL;
413   BIO*   p7bio = NULL;
414   BIO*   wbio = NULL;
415   char*  data = NULL;
416   char   buf[4096];
417   int    i,x;
418 
419   if (!sig_entity || !pubkey) GOTO_ERR("NULL arg(s)");
420   if (!(p7 = get_pkcs7_from_pem(sig_entity))) goto err;
421 
422   /* Hmm, if its clear signed, we already provided the detached sig, but
423    * if its one sig blob, may be PKCS7_get_detached() provides BIO connected
424    * to the detached part. Go figure.
425    */
426 
427   if (detached_data && detached_data_len) {
428     if (!(detached = set_read_BIO_from_buf(detached_data, detached_data_len)))
429       goto err;
430   } else {
431     if (!PKCS7_get_detached(p7))
432       GOTO_ERR("15 cant extract signed data from signed entity (PKCS7_get_detached)");
433   }
434   if (!(p7bio=PKCS7_dataInit(p7,detached))) GOTO_ERR("PKCS7_dataInit");
435 
436   if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
437 
438   /* We now have to 'read' from p7bio to calculate message digest(s).
439    * I also take the opportunity to save the signed data. */
440   for (;;) {
441     i = BIO_read(p7bio,buf,sizeof(buf));
442     if (i <= 0) break;
443     BIO_write(wbio, buf, i);
444   }
445 
446   if (get_written_BIO_data(wbio, &data)==-1) goto err;
447   BIO_free_all(wbio);
448   wbio = NULL;
449 
450   /* We can now verify signatures */
451   if (!(sigs=PKCS7_get_signer_info(p7)))
452     GOTO_ERR("13 no sigs? (PKCS7_get_signer_info)");
453 
454   /* Ok, first we need to, for each subject entry, see if we can verify */
455   for (i=0; i<sk_PKCS7_SIGNER_INFO_num(sigs); i++) {
456     PKCS7_SIGNER_INFO *si;
457 
458     si=sk_PKCS7_SIGNER_INFO_value(sigs,i);
459 
460     /* The bio is needed here only to lookup the message digest context
461      * which presumably now contains the message digest. It will not be
462      * read, and hence its good for any number of iterations. This is so
463      * because MD bios pass the data right thru so they can be stacked
464      * to calculate multiple message digests simultaneously. Clever, eh?
465      */
466 
467 #if 0
468     /* *** this is currently broken and thus disabled. --Sampo */
469     /* verifies by looking up the certificate from certs database,
470      * verifying the validity of the certificate, and finally
471      * validity of the signature */
472 
473     X509_STORE_CTX cert_ctx;
474     x=PKCS7_dataVerify(certs, &cert_ctx, p7bio, p7, si);
475 #else
476     /* just verify the signature, given that we already have certificate
477      * candidate (see crypto/pk7_doit.c around line 675) */
478 
479     if (!(x509 = extract_certificate(pubkey))) goto err;
480     x=PKCS7_signatureVerify(p7bio, p7, si, x509);
481 #endif
482     if (x <= 0) GOTO_ERR("14 sig verify failed");
483 
484 #if 0
485     ASN1_UTCTIME *tm;
486     if ((tm=get_signed_time(si)) != NULL) {
487       //fprintf(stderr,"Signed time:");
488       //ASN1_UTCTIME_print(bio_out,tm);
489       ASN1_UTCTIME_free(tm);
490       //BIO_printf(bio_out,"\n");
491     }
492 #endif
493 #if 0
494     char *str1,*str2;
495     if (get_signed_seq2string(si,&str1,&str2)) {
496       fprintf(stderr,"String 1 is %s\n",str1);
497       fprintf(stderr,"String 2 is %s\n",str2);
498     }
499 #endif
500   }
501 
502   BIO_free_all(p7bio);
503   PKCS7_free(p7);
504   X509_STORE_free(certs);
505   return data;    /* return the signed plain text */
506 
507 err:
508   if (wbio) BIO_free_all(wbio);
509   if (p7bio) BIO_free_all(p7bio);
510   if (p7) PKCS7_free(p7);
511   if (certs) X509_STORE_free(certs);
512   if (data) OPENSSL_free(data);
513   return NULL;
514 }
515 
516 /* =========== C E R T   V E R I F I C A T I O N =========== */
517 
518 /* Called by:  smime_verify_cert */
519 int  /* returns -1 if error, 0 if verfy fail, and 1 if verify OK */
verify_cert(X509 * ca_cert,X509 * cert)520 verify_cert(X509* ca_cert, X509* cert)
521 {
522   EVP_PKEY* pkey = NULL;
523   if (!ca_cert || !cert) GOTO_ERR("NULL arg(s)");
524   if (!(pkey=X509_get_pubkey(ca_cert))) GOTO_ERR("no memory?");
525   return X509_verify(cert, pkey);
526 err:
527   return -1;
528 }
529 
530 /* Called by:  main */
531 int  /* returns -1 if error, 0 if verfy fail, and 1 if verify OK */
smime_verify_cert(const char * ca_cert_pem,const char * cert_pem)532 smime_verify_cert(const char* ca_cert_pem, const char* cert_pem)
533 {
534   X509* ca_cert = NULL;
535   X509* cert = NULL;
536   int ret = -1;
537   if (!ca_cert_pem || !cert_pem) GOTO_ERR("NULL arg(s)");
538   if (!(ca_cert = extract_certificate(ca_cert_pem))) goto err;
539   if (!(cert = extract_certificate(cert_pem))) goto err;
540   ret = verify_cert(ca_cert, cert);
541 err:
542   if (ca_cert) X509_free(ca_cert);
543   if (cert) X509_free(cert);
544   return ret;
545 }
546 
547 /* EOF  -  smime-vfy.c */
548