1 /* smimeutil.h  -  Utility functions for performing S/MIME signatures
2  *                 and encryption.
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  *
8  * Official web site:  http://www.bacus.pt/Net_SSLeay/smime.html
9  * $Id: smimeutil.h,v 1.1 2009-08-30 15:09:26 sampo Exp $
10  *
11  * 11.9.1999, Created. --Sampo
12  * 1.10.1999, added error codes. --Sampo
13  * 5.10.1999, split interface to character based PEM interface (old) and
14  *            data structure based internal interface. --Sampo
15  * 29.10.1999, added prototypes for certification authority. --Sampo
16  *
17  * This module has been developed to support a Lingo XTRA that is supposed
18  * to provide crypto functionality. It may, however, be useful for other
19  * purposes as well. See also smime.c for command line tool.
20  *
21  * Memory management: most routines malloc the results. Freeing them
22  * is application's responsibility. I use libc malloc, but if in doubt
23  * it might be safer to just leak the memory (i.e. don't ever free
24  * it). The library never attempts to free arguments passed to it
25  * (i.e. you can safely pass in pointers to buffers on stack or
26  * string constants).
27  *
28  * ERROR HANDLING
29  *
30  * Most library functions return NULL (pointer) or -1 (length) upon
31  * error.  If you want to know in more detail what happened you should
32  * call smime_get_errors() function. Most error messages are
33  * meaningless to an average application and its user. Meaningful
34  * error messages start by two digit number. Any message not starting
35  * by number should be assumed to be (in this order)
36  *   - lack of memory ("no memory?" is a strong indication of this, but
37  *     could also mean that the malloc arena has been corrupted, beware!)
38  *   - application passed in bad arguments (application programmer error)
39  *   - internal library error (library programmer error or OpenSSL error)
40  *
41  * These meaningful error codes exist
42  *   01  bad private key file or password, private key couldn't be
43  *       decrypted (wrong file? bad line endings?)
44  *   02  bad PKCS12 file format (perhaps wrong file? corrupt file?)
45  *   03  bad PKCS12 import password
46  *   04  bad X509_REQ (pem)file format (perhaps wrong file or bad line endings)
47  *   05  mismatched X509 certificate and private key (wrong files?)
48  *   06  bad DN component name (must be one of the registered ones)
49  *   07  bad attribute name (must be one of the registered ones)
50  *   08  bad characters in DN or attribute value
51  *   09  missing `=' in DN component or attribute value specification or
52  *       specification otherwise badly formatted (perhaps missing newlines?)
53  *   10  bad X509_REQ (pem)file format (perhaps wrong file or bad line endings)
54  *   11  corrupt p7m message (perhaps whitespace or newlines were added)
55  *   12  message decryption failed. Either message was not encrypted
56  *       for the recipient as indicated by certificate (issuer and serial
57  *       number fields do not match recipient info) or private key
58  *       could not open the encryption, i.e. wrong private key. Could
59  *       also indicate sophisticated message corruption.
60  *   13  No signatures found in signature blob. Perhaps its corrupt or
61  *       is really encrypted blob instead.
62  *   14  signature did not verify. Check for message corruption or
63  *       unexpected white space (esp. if message was clear signed)
64  *   15  signed entity did not contain any signed data (corrupt entity?)
65  *   16  missing mime header, e.g. Content-type: multipart/...
66  *
67  */
68 
69 #ifndef _SMIMEUTIL_H
70 #define _SMIMEUTIL_H
71 #ifdef __cplusplus
72 extern "C" {
73 #endif
74 
75 #define SMIME_VERSION "smimeutils v0.7 17.11.1999"
76 
77 #include <stdio.h>  /* snprintf() */
78 #if defined(SMIME_INTERNALS) && !defined(__DIRECTORYSCRIPT__)
79 # include <openssl/bio.h>
80 # include <openssl/x509.h>
81 # include <openssl/evp.h>
82 # include <openssl/pkcs12.h>
83 #endif
84 
85 #ifndef DSEXPORT
86 #define DSEXPORT
87 #endif
88 
89 /* ======= M I M E   M U L T I P A R T   M A N I P U L A T I O N ======= */
90 
91 /* Create MIME multipart/mixed mime entity containing some text and
92  * then up to 3 attachmets. All attachments are base64 encoded so they
93  * can be binary if needed. */
94 
95 DSEXPORT char*
96 mime_mk_multipart(const char* text,
97 	  const char* file1, int len1, const char* type1, const char* name1,
98 	  const char* file2, int len2, const char* type2, const char* name2,
99 	  const char* file3, int len3, const char* type3, const char* name3);
100 
101 /* Create multipart/signed entity (given that detached sig already exists,
102  * see also smime_clear_sign()) */
103 
104 DSEXPORT char*  /* returns smime encoded clear sig blob, or NULL if error */
105 smime_mk_multipart_signed(const char* mime_entity, const char* sig_entity);
106 
107 /* Finds boundary marker from `Content-type: multipart/...; boundary=sep'
108  * header and splits the multiparts into array parts. Lengths of each
109  * part go to lengths array. If parts is NULL, just returns the number
110  * of parts found. Memory for each part is obtained from Malloc. Only
111  * one level of multipart encoding is interpretted, i.e. if one of the
112  * contained parts happens to be a multipart, it needs to be separately
113  * interpretted on a second pass.
114  *
115  * *** WARNING: this is not totally robust and mime compliant, improvements
116  *              welcome. --Sampo
117  */
118 
119 DSEXPORT int  /* returns number of parts, -1 on error */
120 mime_split_multipart(const char* entity,
121 		     int max_parts,  /* how big following arrays are */
122 		     char* parts[],  /* NULL --> just count the parts */
123 		     int lengths[]);
124 
125 /* Add headers */
126 
127 DSEXPORT char* mime_raw_entity(const char* text, const char* type);
128 
129 /* Apply base64 and add headers */
130 
131 DSEXPORT char* mime_base64_entity(const char* data, int len, const char* type);
132 
133 /* CR->CRLF (Mac) and LF->CRLF (Unix) conversion */
134 
135 DSEXPORT char* mime_canon(const char* s);
136 
137 /* ============= S I G N I N G   &   E N C R Y P T I O N ============= */
138 
139 /* Typically signing and encryption involves a sequence of calls like
140  *
141  *  msg = smime_encrypt(pubkey,
142  *           smime_clear_sign(privkey, password,
143  *              mime_mk_multipart(text, file1, type1, name1,
144  *                                      NULL,  NULL,  NULL,
145  *                                      NULL,  NULL,  NULL)));
146  */
147 
148 /* Sign a mime entity, such as produced by mime_mk_multipart(). Signature
149  * is stored as separate mime entity so the message proper stays visible.  */
150 
151 DSEXPORT char*  /* Returns malloc'd buffer which caller must free. NULL on error */
152 smime_clear_sign(const char* privkey,
153 		 const char* password,
154 		 const char* mime_entity);
155 
156 /* Sign a mime entity, such as produced by mime_mk_multipart(). Signature
157  * and entity are output as one base64 blob so the entity is not trivially
158  * visible. */
159 
160 DSEXPORT char*  /* Returns malloc'd buffer which caller must free. NULL on error */
161 smime_sign(const char* privkey,
162 	   const char* password,
163 	   const char* mime_entity);
164 
165 /* Encrypt a mime entity such as produced by smime_clear_sign(). */
166 
167 DSEXPORT char*  /* Returns malloc'd buffer which caller must free. NULL on error */
168 smime_encrypt(const char* pubkey, const char* mime_entity);
169 
170 /* ============= S I G N A T U R E   V E R I F I C A T I O N ==============*/
171 /* ============= A N D   D E C R Y P T I O N ============================= */
172 
173 /* Typically receiver has to know in what order the signature and encryption
174  * were applied (usually encryption is outermost) and then call these
175  * functions in right order, e.g:
176  */
177 
178 DSEXPORT int  /* returns size of data, -1 on error */
179 smime_decrypt(const char* privkey,
180 	      const char* passwd,
181 	      const char* enc_entity,
182 	      char** data_out);
183 
184 DSEXPORT long  /* return serial on success, -1 on failure */
185 smime_get_signer_info(const char* signed_entity,
186 		      int info_ix,      /* 0 = first signer. Used to iterate */
187 		      char** issuer);   /* DN of the issuer */
188 
189 /* smime_verify_signature can be used to verify both signed entities
190  * and clear signatures. In the first case you must pass NULL on
191  * detached_data parameter. The contents of signed entity are malloc'd
192  * and returned (i.e. you must free it). In the clear sig case, detached
193  * data is returned without malloc. */
194 
195 DSEXPORT char* /* returns contents of the signed message, NULL if error */
196 smime_verify_signature(const char* pubkey,
197 		       const char* sig_entity,     /* signed entity
198 						      or just the sigature */
199 		       const char* detached_data,  /* possibly NULL */
200 		       int detached_data_len);
201 
202 DSEXPORT int  /* returns -1 if error, 0 if verfy fail, and 1 if verify OK */
203 smime_verify_cert(const char* ca_cert_pem, const char* cert_pem);
204 
205 DSEXPORT char*  /* returns pem encoded certificate, or NULL if error */
206 smime_ca(const char* ca_id_pem,
207 	 const char* passwd,
208 	 const char* req_pem,
209 	 const char* start_date,
210 	 const char* end_date,
211 	 long serial,
212 	 const char* basic_constraints,
213 	 const char* cert_type,
214 	 const char* key_usage,
215 	 const char* comment);
216 
217 /* ============= K E Y   G E N E R A T I O N ==============*/
218 
219 /* char** values are out parameters. They return malloced values.
220  * random is extra random number seed. passowrd is the password used
221  * to encrypt the private key. identifiaction is a newline separated list
222  * of attributes to include in certification request. Each line has
223  * format: `name=value\n'
224  */
225 
226 DSEXPORT int
227 smime_keygen(const char* dn,      /* distinguished name  to include in cert */
228 	     const char* attr,    /* additional attributes to send */
229 	     const char* passwd,  /* password for encrypting the private key */
230 	     const char* comment, /* comment to include in self signed cert */
231 	     char** priv,         /* pem encoded private key */
232 	     char** x509ss,       /* pem encoded self signed cert */
233 	     char** request);     /* pem encoded certificate request */
234 
235 /* Convert pem formatted certificate and private key into PKCS12
236  * object suitable for importing to browsers.
237  *
238  * openssl pkcs12 -name "Test friendly name" -info -in cert.pem -inkey priv.pem -chain -export >pkcs12
239  */
240 
241 DSEXPORT int
242 smime_pem_to_pkcs12(const char* friendly_name,  /* e.g. foo@bar.com */
243 		    const char* x509_cert_pem,  /* must have only one */
244 		    const char* priv_key_pem,
245 		    const char* priv_passwd,    /* used to open private key */
246 		    const char* pkcs12_passwd,  /* used to encrypt pkcs12 */
247 		    char** pkcs12);
248 
249 /* more generic version that allows inclusion of multiple certificates */
250 
251 DSEXPORT int
252 smime_pem_to_pkcs12_generic(const char* friendly_name,  /* e.g. foo@bar.com */
253 			    const char* x509_certs_pem,  /* can have many */
254 		    const char* priv_key_pem,
255 		    const char* priv_passwd,    /* used to open private key */
256 		    const char* pkcs12_passwd,  /* used to encrypt pkcs12 */
257 		    char** pkcs12);
258 
259 /* Extract certificate(s) and public key(s) from PKCS12 structure.
260  * Can be used to extract only one or the other by passing NULL
261  * to appropriate OUT parameter. Can only extract last private key
262  * and last certificate (so beware if passing a certificate chain).
263  *
264  * openssl pkcs12 <foo.p12
265  */
266 
267 DSEXPORT int
268 smime_pkcs12_to_pem(const char* pkcs12, int pkcs12_len,
269 		    const char* pkcs12_passwd,  /* used to decrypt pkcs12 */
270 		    const char* priv_passwd,    /* used to enc. private key */
271 		    char** priv_key_pem,        /* OUT private key */
272 		    char** x509_cert_pem);      /* OUT certificate */
273 
274 /* more generic because handles multiple certificates and private keys
275    in key bags */
276 
277 DSEXPORT int
278 smime_pkcs12_to_pem_generic(const char* pkcs12, int pkcs12_len,
279 		    const char* pkcs12_passwd,  /* used to decrypt pkcs12 */
280 		    const char* priv_passwd,    /* used to enc. private key */
281 		    char** priv_key_pem,        /* OUT private key(s) */
282 		    char** x509_cert_pem);      /* OUT certificate(s) */
283 
284 /* Obtain some human readable descriptions of the certificate. This is
285  * important, for example, to verify if two certificates have the same
286  * public key modulus.
287  */
288 
289 DSEXPORT long  /* return serial number, -1 on failure */
290 smime_get_cert_info(const char* x509_cert_pem,
291 		    char** modulus,      /* public key modulus */
292 		    char** fingerprint); /* finger print that identifies */
293 
294 DSEXPORT char* /* public key modulus */
295 smime_get_req_modulus(const char* request_pem);
296 
297 /* Get distinguished name information from the certificate */
298 
299 DSEXPORT long  /* return serial number, -1 on failure */
300 smime_get_cert_names(const char* x509_cert_pem,
301 		    char** subject_DN,   /* who the certificate belongs to */
302 		    char** issuer_DN);   /* who signed the certificate */
303 
304 DSEXPORT char* /* subject_DN - who the request belongs to */
305 smime_get_req_name(const char* request_pem);
306 
307 DSEXPORT char* /* string representation of some attributes */
308 smime_get_req_attr(const char* request_pem);
309 
310 /* Calculate a hash over any string (I use it for modulus) */
311 
312 DSEXPORT char*  /* returns the md5 hash as hex dump */
313 smime_md5(const char* modulus);
314 
315 DSEXPORT char* /* 25 bit hash as string like `*Z4K67W*' or NULL if error */
316 smime_get_req_hash(const char* request_pem);
317 
318 #ifdef SMIME_INTERNALS
319 
320 /* These are binary versions of the above functions. Generally these
321  * eat and return OpenSSL data structures instead of pem encodings. */
322 
323 DSEXPORT PKCS12*
324 x509_and_pkey_to_pkcs12(const char* friendly_name,  /* e.g. foo@bar.com */
325 	      X509*       x509,           /* cert that goes with the pkey */
326 	      EVP_PKEY*   pkey,           /* private key */
327 	      const char* pkcs12_passwd); /* used to encrypt pkcs12 */
328 
329 DSEXPORT int
330 pkcs12_to_x509_and_pkey(PKCS12* p12,
331 	      const char* pkcs12_passwd,  /* used to decrypt pkcs12 */
332 	      X509**      x509_out,       /* cert that goes with the pkey */
333 	      EVP_PKEY**  pkey_out);      /* private key */
334 
335 DSEXPORT long  /* return serial number, -1 on failure */
336 get_cert_info(X509* x509,
337 	      char** modulus,       /* public key modulus */
338 	      char** fingerprint);  /* finger print that identifies */
339 
340 DSEXPORT long  /* return serial number, -1 on failure */
341 get_cert_names(X509* x509,
342 	       char** subject_DN,   /* who the certificate belongs to */
343 	       char** issuer_DN);    /* who signed the certificate */
344 
345 DSEXPORT char* /* public key modulus */
346 get_req_modulus(X509_REQ* req);
347 
348 DSEXPORT char* /* subject_DN - who the request belongs to */
349 get_req_name(X509_REQ* req);
350 
351 DSEXPORT char* /* new line separated list of attribute value pairs */
352 get_req_attr(X509_REQ* req);
353 
354 DSEXPORT char*  /* hash, ready to print, or NULL if error */
355 get_req_hash(X509_REQ* req);
356 
357 DSEXPORT char*  /* returns smime encoded clear signed blob, or NULL if error */
358 clear_sign(X509* x509, EVP_PKEY* pkey, const char* mime_entity);
359 
360 DSEXPORT char*  /* returns smime blob, NULL if error */
361 sign(X509* x509, EVP_PKEY* pkey, const char* mime_entity);
362 
363 DSEXPORT int  /* returns -1 if error, 0 if verfy fail, and 1 if verify OK */
364 verify_cert(X509* ca_cert, X509* cert);
365 
366 DSEXPORT char* encrypt1(X509* x509, const char* mime_entity);
367 
368 DSEXPORT int  /* return size of data, -1 on failure */
369 decrypt(X509* x509, EVP_PKEY* pkey, const char* enc_entity, char** data_out);
370 
371 DSEXPORT int
372 keygen(const char* dn, const char* attr, const char* comment,
373        EVP_PKEY** pkey_out,
374        X509** x509ss_out,
375        X509_REQ** req_out);
376 
377 /* sign a request into a X509 certificate */
378 
379 DSEXPORT X509*  /* returns signed certificate, or NULL if error */
380 certification_authority(X509* ca_cert,
381 			EVP_PKEY* ca_pkey,
382 			X509_REQ* req,
383 			const char* start_date,
384 			const char* end_date,
385 			long serial,
386 			const char* basic_constraints,
387 			const char* cert_type,
388 			const char* key_usage,
389 			const char* comment);
390 
391 #endif
392 
393 /* ======================= U T I L I T I E S ======================= */
394 
395 extern char randomfile[256];
396 
397 /* initializes EVP algorithm tables and injects randomness into
398  * system. If random file existed it is read as well and 0 (for
399  * success) is returned. If random file did not exist, it will be
400  * created (if permissions allow) and -1 is returned. On that occasion
401  * it is advisable to arrange some real randomness (such as movements of
402  * mouse, times between key presses, /dev/random, etc.) and call
403  * init again. */
404 
405 DSEXPORT int smime_init(const char* random_file, const char* randomness, int randlen);
406 
407 /* encp=0 base64->binary, enc=1 binary->base64 */
408 
409 DSEXPORT int smime_base64(int encp, const char* data, int len, char** b64);
410 
411 /* stores smime library level error. The buffer only has meaningful
412  * values if an error has happened. You must detect the error from
413  * return value of a function (NULL or -1) before looking here or
414  * calling smime_get_errors(). */
415 extern char smime_error_buf[256];
416 
417 DSEXPORT char* smime_get_errors();
418 DSEXPORT char* smime_hex(const char* data, int len);
419 DSEXPORT char* smime_dotted_hex(const char* data, int len);
420 
421 /* ================= I N T E R N A L   U T I L I T I E S ================ */
422 
423 #ifdef SMIME_INTERNALS
424 
425 /* Hard coded mime separators. Hope the content will never have these. */
426 
427 #define SEP "42_is_the_answer"   /* MIME multipart boundary separator */
428 #define SIG "42_is_the_question" /* MIME multipart/signed boundary sep */
429 
430 /* To guard agains any macintosh brain damage where \n == \015 */
431 
432 #define CR    "\015"
433 #define LF    "\012"
434 #define CRLF  "\015\012"
435 
436 /* Initialize a memory BIO to have certain content */
437 
438 DSEXPORT BIO* set_read_BIO_from_buf(const char* buf, int len);
439 
440 DSEXPORT int get_written_BIO_data(BIO* wbio, char** data);
441 
442 /* Get private key from buffer full of encrypted stuff */
443 
444 DSEXPORT EVP_PKEY* open_private_key(const char* privatekey_pem, const char* password);
445 DSEXPORT int write_private_key(EVP_PKEY* pkey, const char* passwd, char** priv);
446 
447 /* Extract a certificate from pem encoding */
448 
449 DSEXPORT X509* extract_certificate(const char* cert);
450 
451 DSEXPORT int /* returns length of the PEM encoding */
452 write_certificate(X509* x509, char** x509_cert_pem);
453 
454 DSEXPORT X509_REQ* extract_request(const char* req);
455 DSEXPORT int write_request(X509_REQ* x509_req, char** x509_req_pem);
456 
457 DSEXPORT PKCS12* load_PKCS12(const char* pkcs12, int pkcs12_len);
458 DSEXPORT int save_PKCS12(PKCS12* p12, char** pkcs12_out);
459 
460 DSEXPORT int password_callback(char* buf, int buf_size, int x /*not used*/, void* password);
461 
462 DSEXPORT char* concat(char* b, const char* s);
463 DSEXPORT char* concatmem(char* b, const char* s, int len);
464 
465 /* WARNING: returned value can not be freed */
466 DSEXPORT char*  /* returns pointer to within buf. Buf is modified. */
467 cut_pem_markers_off(char* buf, int len, char* algo_name);
468 
469 DSEXPORT char*  /* returns new buf */
470 wrap_in_pem_markers(const char* buf, char* algo_name);
471 
472 /* Adds some of the most commonly wanted extensions
473  *
474  * Examples:
475  *   basic_constraints: CA:TRUE,pathlen:3
476  *   cert_type: client,server,email,objsign,sslCA,emailCA,objCA
477  *   key_usage: digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign
478  *   comment: dont trust me ;-)
479  */
480 
481 DSEXPORT int
482 add_some_X509v3_extensions(X509* cert,
483 			   const char* basic_constraints,
484 			   const char* cert_type,
485 			   const char* key_usage,
486 			   const char* comment);
487 
488 /* Macro to make error reporting more friendly while still easy. */
489 
490 #if 1
491 # define GOTO_ERR(x) do{ snprintf(smime_error_buf, sizeof(smime_error_buf), \
492       "%s (%s:%d)\n", (x), __FILE__, __LINE__); \
493       smime_error_buf[sizeof(smime_error_buf)-1]='\0'; goto err; }while(0)
494 #else
495 # define GOTO_ERR(x) goto err
496 #endif
497 
498 #undef DEBUGLOG
499 
500 #ifdef DEBUGLOG
501 extern FILE* Log;
502 # define LOG(x) do{ if (Log) { fprintf(Log, "%s %d: %s\n", \
503                   __FILE__, __LINE__, (x)); fflush(Log); } }while(0)
504 # define LOG2(s,x) do{ if (Log) { fprintf(Log, "%s %d: " s "\n", \
505                   __FILE__, __LINE__, (x)); fflush(Log); } }while(0)
506 #else
507 #if !defined(DSPROXY) && !defined(__DIRECTORYSCRIPT__)
508 #define LOG(x)
509 #define LOG2(s,x)
510 #endif
511 #endif
512 
513 #endif /* SMIME_INTERNALS */
514 
515 #ifdef __cplusplus
516 }
517 #endif
518 
519 #endif /* _SMIMEUTIL_H */
520