1 /* smimeutil.c  -  Utility functions for performing S/MIME signatures
2  *                 and encryption.
3  *
4  * Copyright (c) 1999,2004 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, divided to smime-enc.c, smime-vfy.c, smimemime.c and smimeutil.c
13  * 9.10.1999, reviewed for double frees --Sampo
14  * 18.10.1999, added CR_PARANOIA ifdefs. THis define is useful on platforms
15  *             like Mac that use CR as line termination. OpenSSL PEM
16  *             parsing routines do not grog CR so we need to preconvert
17  *             CR to CRLF to guarantee easy operation. --Sampo
18  * 10.10.2004, fixed long term annoyance where empty password did still encypt. Now
19  *             empty password causes no encryption what so ever. --Sampo
20  *
21  * This module has been developed to support a Lingo XTRA that is supposed
22  * to provide crypto functionality. It may, however, be useful for other
23  * purposes as well.
24  *
25  * This is a very simple S/MIME library. For example the multipart
26  * boundary separators are hard coded and no effort is made to verify
27  * that mime entities are in their canonical form before signing (the
28  * caller should make sure they are, canonical form means using CRLF
29  * as line termination, among other things). Also the multipart functionality
30  * only understands up to 3 attachments. For many tasks this is enough,
31  * but if its not, feel free to write more generic utilities.
32  *
33  * Memory management: most routines malloc the results. Freeing them is
34  * application's responsibility. I use libc malloc, but if in doubt
35  * it might be safer to just leak the memory (i.e. don't ever free it).
36  * This library works entirely in memory, so maximum memory consumption
37  * might be more than twice the total size of all files to be encrypted.
38  */
39 
40 #include "platform.h"
41 
42 #include <stdio.h>
43 #include <string.h>
44 #include <time.h>
45 
46 #if defined(macintosh) || defined(__MWERKS__)
47 #include "macglue.h"
48 #endif
49 
50 #include "logprint.h"
51 
52 #include <openssl/crypto.h>
53 #include <openssl/buffer.h>
54 #include <openssl/bio.h>
55 #include <openssl/x509.h>
56 #include <openssl/pem.h>
57 #include <openssl/err.h>
58 #include <openssl/rand.h>
59 
60 #define SMIME_INTERNALS  /* we want also our internal helper functions */
61 #include "smimeutil.h"
62 
63 /* ======================= U T I L I T I E S ======================= */
64 
65 char smime_error_buf[256];  /* stores smime library-level error */
66 char randomfile[256] = "random.txt";
67 
68 #ifdef DEBUGLOG
69 FILE* Log = NULL;
70 #endif
71 
72 /* initializes EVP algorithm tables and injects randomness into
73  * system. If random file existed it is read as well and 0 (for
74  * success) is returned. If random file did not exist, it will be
75  * created (if permissions allow) and -1 is returned. On that occasion
76  * it is advisable to arrange some real randomness (such as movements of
77  * mouse, times between key presses, /dev/random, etc.) and call
78  * init again.
79  */
80 
81 /* Called by:  main */
smime_init(const char * random_file,const char * randomness,int randlen)82 int smime_init(const char* random_file, const char* randomness, int randlen)
83 {
84   time_t t;
85   OpenSSL_add_all_algorithms();  /* calling this multiple times does not seem to have any negative effect. */
86   OpenSSL_add_all_ciphers();  /* Needed to avoid 10069:error:0906B072:PEM routines:PEM_get_EVP_CIPHER_INFO:unsupported encryption:pem_lib.c:481: */
87   OpenSSL_add_all_digests();
88 
89 #ifdef DEBUGLOG
90   Log = fopen("smimeutil.log", "w");
91   LOG("Log opened");
92 #endif
93 
94   LOG_PRINT("smime_init");
95   t = time(NULL);
96   RAND_seed(&t,sizeof(t));
97   if (randomness) RAND_seed(randomness, randlen);
98 
99 #ifdef WINDOWS
100   LOG_PRINT("RAND_screen...");
101   RAND_screen(); /* Loading video display memory into random state */
102 #endif
103   if (random_file) {
104     strncpy(randomfile, random_file, sizeof(randomfile));
105     randomfile[sizeof(randomfile)-1] = '\0';
106   }
107   if (RAND_load_file(randomfile,1024L*1024L)) {
108     RAND_seed(&t,sizeof(t));
109     strcpy(smime_error_buf, SMIME_VERSION " randomness initialized");
110     return 0;
111   }
112   strcpy(smime_error_buf, SMIME_VERSION " no randomfile");
113   RAND_seed(&t,sizeof(t));
114   RAND_write_file(randomfile);  /* create random file if possible */
115 
116   return -1;
117 }
118 
119 /* Initialize a memory BIO to have certain content */
120 
121 /* Called by:  encrypt1, extract_certificate, extract_request, get_pkcs7_from_pem, load_PKCS12, open_private_key, smime_base64, smime_pkcs12_to_pem_generic, smime_sign_engine, smime_verify_signature */
set_read_BIO_from_buf(const char * buf,int len)122 BIO* set_read_BIO_from_buf(const char* buf, int len)
123 {
124   BIO* rbio;
125   BUF_MEM* bm;
126   if (!buf) GOTO_ERR("NULL file buffer");
127   if (len == -1) len = strlen(buf);
128   LOG_PRINT3("set_read_BIO_from_buf %x, len %d", buf, len);
129   if (!(rbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
130   if (!(bm = BUF_MEM_new()))  GOTO_ERR("no memory?");
131   if (!BUF_MEM_grow(bm, len)) GOTO_ERR("no memory?");
132   memcpy(bm->data, buf, len);
133   BIO_set_mem_buf(rbio, bm, 0 /*not used*/);
134   LOG_PRINT("ok");
135   return rbio;
136 err:
137   return NULL;
138 }
139 
140 /* Flushes a write BIO and returns the accumulated data as one malloc'd blob
141  * returns length or -1 if error */
142 
143 /* Called by:  decrypt, get_cert_info, get_req_modulus, save_PKCS12, smime_base64, smime_pkcs12_to_pem_generic x2, smime_verify_signature, write_certificate, write_private_key, write_request */
get_written_BIO_data(BIO * wbio,char ** data)144 int get_written_BIO_data(BIO* wbio, char** data)
145 {
146   int n;
147   char* p;
148   if (!data) GOTO_ERR("NULL arg");
149   *data = NULL;
150   BIO_flush(wbio);
151   n = BIO_get_mem_data(wbio,&p);
152   LOG_PRINT3("get_written_BIO_data: %x %d bytes", p, n);
153   if (!((*data)=(char*)OPENSSL_malloc(n+1))) GOTO_ERR("no memory?");
154   memcpy(*data, p, n);
155   (*data)[n] = '\0';
156   return n;
157 err:
158   return -1;
159 }
160 
161 /* Callback for supplying the pesky password. */
162 
163 /* Called by: */
password_callback(char * buf,int buf_size,int x,void * password)164 int password_callback(char* buf, int buf_size, int x /*not used*/, void* password)
165 {
166   int n;
167   if (!password) {
168     strcpy(buf, "");
169     return 0;
170   }
171   n = strlen((char*)password);
172   if (n >= buf_size) n = buf_size-1;
173   memcpy(buf, (char*)password, n);
174   buf[n] = '\0';
175   return n;
176 }
177 
178 /* Get private key from buffer full of encrypted stuff */
179 
180 /* Called by:  smime_ca, smime_clear_sign, smime_decrypt, smime_sign */
open_private_key(const char * privatekey_pem,const char * password)181 EVP_PKEY* open_private_key(const char* privatekey_pem, const char* password)
182 {
183   EVP_PKEY* pkey = NULL;
184   BIO* rbio = NULL;
185   LOG_PRINT3("open_private_key: %x %x", privatekey_pem, password);
186 #ifdef CR_PARANOIA
187   if (!(privatekey_pem = mime_canon(privatekey_pem))) GOTO_ERR("no memory?");
188   LOG_PRINT("CR paranoia enabled");
189 #endif
190   if (!(rbio = set_read_BIO_from_buf(privatekey_pem, -1))) goto err;
191   if (!(pkey=PEM_read_bio_PrivateKey(rbio,NULL, password_callback,
192 				     (void*)password)))
193     GOTO_ERR("01 bad password or badly formatted private key pem file (PEM_read_bio_PrivateKey)");
194   LOG_PRINT("done");
195   BIO_free(rbio);
196 #ifdef CR_PARANOIA
197   if (privatekey_pem) Free((void*)privatekey_pem);
198 #endif
199   return pkey;
200 
201 err:
202 #ifdef CR_PARANOIA
203   if (privatekey_pem) Free((void*)privatekey_pem);
204 #endif
205   if (pkey) EVP_PKEY_free(pkey);
206   if (rbio) BIO_free(rbio);
207   LOG_PRINT("error");
208   return NULL;
209 }
210 
211 /* Called by:  smime_keygen, smime_pkcs12_to_pem */
write_private_key(EVP_PKEY * pkey,const char * passwd,char ** priv_pem_OUT)212 int write_private_key(EVP_PKEY* pkey, const char* passwd, char** priv_pem_OUT)
213 {
214   int len = -1;
215   BIO* wbio=NULL;
216   if (!passwd || !priv_pem_OUT || !pkey) GOTO_ERR("NULL arg(s)");
217   *priv_pem_OUT = NULL;
218   if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
219   LOG_PRINT("write_private_key");
220   if (!PEM_write_bio_PrivateKey(wbio, pkey, *passwd ? EVP_des_ede3_cbc() : 0,
221 				*passwd ? (unsigned char*)passwd:0, strlen(passwd),
222 				NULL,NULL))
223     GOTO_ERR("PEM_write_bio_PrivateKey (bad passwd, no memory?)");
224   len = get_written_BIO_data(wbio, priv_pem_OUT);
225 err:
226   if (wbio) BIO_free_all(wbio);
227   return len;
228 }
229 
230 /* Extract a certificate from pem encoding */
231 
232 /* Called by:  smime_ca, smime_clear_sign, smime_decrypt, smime_encrypt, smime_get_cert_info, smime_get_cert_names, smime_sign, smime_verify_cert x2, smime_verify_signature */
extract_certificate(const char * cert_pem)233 X509* extract_certificate(const char* cert_pem)
234 {
235   X509* x509 = NULL;
236   BIO* rbio = NULL;
237   LOG_PRINT2("extract_certificate %x", cert_pem);
238 #ifdef CR_PARANOIA
239   if (!(cert_pem = mime_canon(cert_pem))) GOTO_ERR("no memory?");
240   LOG_PRINT("CR paranoia enabled");
241 #endif
242   if (!(rbio = set_read_BIO_from_buf(cert_pem, -1))) goto err;
243   if (!(x509=PEM_read_bio_X509(rbio,NULL,NULL,NULL)))
244     GOTO_ERR("10 badly formatted X509 certificate pem file (PEM_read_bio_X509)");
245   LOG_PRINT("done");
246 err:
247 #ifdef CR_PARANOIA
248   if (cert_pem) Free((void*)cert_pem);
249 #endif
250   if (rbio) BIO_free(rbio);
251   return x509;
252 }
253 
254 /* Called by:  smime_ca, smime_keygen, smime_pkcs12_to_pem */
write_certificate(X509 * x509,char ** x509_cert_pem_OUT)255 int write_certificate(X509* x509, char** x509_cert_pem_OUT)
256 {
257   BIO* wbio = NULL;
258   int len = -1;
259   if (!x509 || !x509_cert_pem_OUT) GOTO_ERR("NULL arg");
260   *x509_cert_pem_OUT = NULL;
261   if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
262   LOG_PRINT("write_certificate");
263   PEM_write_bio_X509(wbio, x509);
264   len = get_written_BIO_data(wbio, x509_cert_pem_OUT);
265 err:
266   if (wbio) BIO_free_all(wbio);
267   return len;
268 }
269 
270 /* Called by:  smime_ca, smime_get_req_attr, smime_get_req_modulus, smime_get_req_name */
extract_request(const char * req_pem)271 X509_REQ* extract_request(const char* req_pem)
272 {
273   X509_REQ* x509_req = NULL;
274   BIO* rbio = NULL;
275   LOG_PRINT2("extract_request %x", req_pem);
276 #ifdef CR_PARANOIA
277   if (!(req_pem = mime_canon(req_pem))) GOTO_ERR("no memory?");
278   LOG_PRINT("CR paranoia enabled");
279 #endif
280   if (!(rbio = set_read_BIO_from_buf(req_pem, -1))) goto err;
281   if (!(x509_req = PEM_read_bio_X509_REQ(rbio,NULL,NULL,NULL)))
282     GOTO_ERR("04 badly formatted certificate request pem file (PEM_read_bio_x509_REQ)");
283   LOG_PRINT("done");
284 err:
285 #ifdef CR_PARANOIA
286   if (req_pem) Free((void*)req_pem);
287 #endif
288   if (rbio) BIO_free(rbio);
289   return x509_req;
290 }
291 
292 /* Called by:  smime_keygen */
write_request(X509_REQ * x509_req,char ** x509_req_pem_OUT)293 int write_request(X509_REQ* x509_req, char** x509_req_pem_OUT)
294 {
295   BIO* wbio = NULL;
296   int len = -1;
297   if (!x509_req || !x509_req_pem_OUT) GOTO_ERR("NULL arg");
298   *x509_req_pem_OUT = NULL;
299   if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
300   LOG_PRINT("write_request");
301   PEM_write_bio_X509_REQ(wbio, x509_req);
302   len = get_written_BIO_data(wbio, x509_req_pem_OUT);
303 err:
304   if (wbio) BIO_free_all(wbio);
305   return len;
306 }
307 
308 /* Called by:  smime_pkcs12_to_pem */
load_PKCS12(const char * pkcs12,int pkcs12_len)309 PKCS12* load_PKCS12(const char* pkcs12, int pkcs12_len)
310 {
311   BIO* rbio = NULL;
312   PKCS12* p12 = NULL;
313   if (!(rbio = set_read_BIO_from_buf((char*)pkcs12, pkcs12_len))) goto err;
314   if (!(p12 = d2i_PKCS12_bio(rbio, NULL)))
315     GOTO_ERR("02 bad PKCS12 file format (d2i_PKCS12_bio)");
316 err:
317   if (rbio) BIO_free(rbio);
318   return p12;
319 
320 }
321 
322 /* Called by: */
save_PKCS12(PKCS12 * p12,char ** pkcs12_out)323 int save_PKCS12(PKCS12* p12, char** pkcs12_out)
324 {
325   BIO* wbio = NULL;
326   int len = -1;
327   if (!p12 || !pkcs12_out) GOTO_ERR("NULL arg(s)");
328   *pkcs12_out = NULL;
329   if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
330   i2d_PKCS12_bio(wbio, p12);  /* der encode it */
331   len = get_written_BIO_data(wbio, pkcs12_out);
332 err:
333   if (wbio) BIO_free_all(wbio);
334   return len;
335 }
336 
337 /* Called by:  get_cert_info */
smime_dotted_hex(const char * data,int len)338 char* smime_dotted_hex(const char* data, int len)
339 {
340   int j;
341   char* p;
342   char* buf;
343   if (!data || !len) GOTO_ERR("NULL or bad arg");
344   if (!(buf = p = (char*)OPENSSL_malloc(len*3+1))) GOTO_ERR("no memory?");
345   for (j=0; j<len; j++) {
346     sprintf(p,"%02X:",(unsigned char)data[j]);
347     p+=3;
348   }
349   p[-1] = '\0';  /* change last : to \0 */
350   return buf;
351 err:
352   return NULL;
353 }
354 
355 /* Called by:  smime_md5 */
smime_hex(const char * data,int len)356 char* smime_hex(const char* data, int len)
357 {
358   int j;
359   char* p;
360   char* buf;
361   if (!data || !len) GOTO_ERR("NULL or bad arg");
362   if (!(buf = p = (char*)OPENSSL_malloc(len*2+1))) GOTO_ERR("no memory?");
363   for (j=0; j<len; j++) {
364     sprintf(p,"%02X",(unsigned char)data[j]);
365     p+=2;
366   }
367   return buf;
368 err:
369   return NULL;
370 }
371 
372 /* Called by:  main x28 */
smime_get_errors()373 char* smime_get_errors()
374 {
375   BIO* wbio;
376   char* p;
377   if (!(wbio = BIO_new(BIO_s_mem()))) return smime_error_buf;
378   BIO_puts(wbio, smime_error_buf);
379   ERR_load_crypto_strings();
380   ERR_print_errors(wbio);
381   BIO_get_mem_data(wbio,&p);
382   return p;  /* just leak the wbio */
383 }
384 
385 /* EOF  -  smimeutil.c */
386