1 /*
2   Copyright 2021 Northern.tech AS
3 
4   This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5 
6   This program is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published by the
8   Free Software Foundation; version 3.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
18 
19   To the extent this program is licensed as part of the Enterprise
20   versions of CFEngine, the applicable Commercial Open Source License
21   (COSL) may apply to this file if you as a licensee so wish it. See
22   included file COSL.txt.
23 */
24 
25 #include <crypto.h>
26 
27 #include <openssl/err.h>                                        /* ERR_* */
28 #include <openssl/rand.h>                                       /* RAND_* */
29 #include <openssl/bn.h>                                         /* BN_* */
30 #include <libcrypto-compat.h>
31 
32 #include <cf3.defs.h>
33 #include <lastseen.h>
34 #include <files_interfaces.h>
35 #include <hash.h>
36 #include <pipes.h>
37 #include <mutex.h>
38 #include <known_dirs.h>
39 #include <bootstrap.h>
40 #include <misc_lib.h>                   /* UnexpectedError,ProgrammingError */
41 #include <file_lib.h>
42 
43 #ifdef DARWIN
44 // On Mac OSX 10.7 and later, majority of functions in /usr/include/openssl/crypto.h
45 // are deprecated. No known replacement, so shutting up compiler warnings
46 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
47 #endif
48 
49 #if OPENSSL_VERSION_NUMBER < 0x10100000
50 /* The deprecated is the easy way to setup threads for OpenSSL. */
51 #ifdef OPENSSL_NO_DEPRECATED
52 void CRYPTO_set_id_callback(unsigned long (*func)(void));
53 #endif
54 #endif
55 
56 static void RandomSeed(void);
57 static void SetupOpenSSLThreadLocks(void);
58 static void CleanupOpenSSLThreadLocks(void);
59 
60 /* TODO move crypto.[ch] to libutils. Will need to remove all manipulation of
61  * lastseen db. */
62 
63 static bool crypto_initialized = false; /* GLOBAL_X */
64 
CryptoLastErrorString()65 const char *CryptoLastErrorString()
66 {
67     const char *errmsg = ERR_reason_error_string(ERR_get_error());
68     return (errmsg != NULL) ? errmsg : "no error message";
69 }
70 
CryptoInitialize()71 void CryptoInitialize()
72 {
73     if (!crypto_initialized)
74     {
75         SetupOpenSSLThreadLocks();
76         OpenSSL_add_all_algorithms();
77         OpenSSL_add_all_digests();
78         ERR_load_crypto_strings();
79 
80         RandomSeed();
81 
82         crypto_initialized = true;
83     }
84 }
85 
CryptoDeInitialize()86 void CryptoDeInitialize()
87 {
88     if (crypto_initialized)
89     {
90         char randfile[CF_BUFSIZE];
91         snprintf(randfile, CF_BUFSIZE, "%s%crandseed",
92                  GetWorkDir(), FILE_SEPARATOR);
93 
94         /* Only write out a seed if the file doesn't exist
95          * and we have enough entropy to do so. If RAND_write_File
96          * returns a bad value, delete the poor seed.
97          */
98         if (access(randfile, R_OK) && errno == ENOENT && RAND_write_file(randfile) != 1024)
99         {
100             Log(LOG_LEVEL_WARNING,
101                 "Could not write randomness to '%s'", randfile);
102             unlink(randfile); /* do not reuse entropy */
103         }
104 
105         chmod(randfile, 0600);
106         EVP_cleanup();
107         CleanupOpenSSLThreadLocks();
108         ERR_free_strings();
109         crypto_initialized = false;
110     }
111 }
112 
RandomSeed(void)113 static void RandomSeed(void)
114 {
115     /* 1. Seed the weak C PRNGs. */
116 
117     /* Mix various stuff. */
118     pid_t pid = getpid();
119     size_t fqdn_len = strlen(VFQNAME) > 0 ? strlen(VFQNAME) : 1;
120     time_t start_time = CFSTARTTIME;
121     time_t now = time(NULL);
122 
123     srand((unsigned) pid      * start_time ^
124           (unsigned) fqdn_len * now);
125     srand48((long)  pid      * start_time ^
126             (long)  fqdn_len * now);
127 
128     /* 2. Seed the strong OpenSSL PRNG. */
129 
130 #ifndef __MINGW32__
131     RAND_poll();                                        /* windows may hang */
132 #else
133     RAND_screen();                       /* noop unless openssl is very old */
134 #endif
135 
136     if (RAND_status() != 1)
137     {
138         /* randseed file is written on deinitialization of crypto system */
139         char randfile[CF_BUFSIZE];
140         snprintf(randfile, CF_BUFSIZE, "%s%crandseed",
141                  GetWorkDir(), FILE_SEPARATOR);
142         Log(LOG_LEVEL_VERBOSE, "Looking for a source of entropy in '%s'",
143             randfile);
144 
145         if (RAND_load_file(randfile, -1) != 1024)
146         {
147             Log(LOG_LEVEL_CRIT,
148                 "Could not read randomness from '%s'", randfile);
149             unlink(randfile); /* kill randseed if error reading it */
150         }
151 
152         /* If we've used the random seed, then delete */
153         unlink(randfile);
154     }
155 }
156 
157 /* PEM functions need the const cast away, but hopefully the default
158  * call-back doesn't actually modify its user-data. */
159 static const char priv_passphrase[] = PRIVKEY_PASSPHRASE;
160 
161 /**
162  * @param[in] priv_key_path path to the private key to use (%NULL to use the default)
163  * @param[in] pub_key_path path to the private key to use (%NULL to use the default)
164  * @param[out] priv_key a place to store the loaded private key (or %NULL to
165  *             use the global PRIVKEY variable)
166  * @param[out] pub_key a place to store the loaded public key (or %NULL to
167  *             use the global PUBKEY variable)
168  * @return true the error is not so severe that we must stop
169  */
LoadSecretKeys(const char * const priv_key_path,const char * const pub_key_path,RSA ** priv_key,RSA ** pub_key)170 bool LoadSecretKeys(const char *const priv_key_path,
171                     const char *const pub_key_path,
172                     RSA **priv_key, RSA **pub_key)
173 {
174     {
175         char *privkeyfile = NULL;
176         if (priv_key_path == NULL)
177         {
178             privkeyfile = PrivateKeyFile(GetWorkDir());
179         }
180         FILE *fp = safe_fopen(privkeyfile != NULL ? privkeyfile : priv_key_path, "r");
181         if (!fp)
182         {
183             /* VERBOSE in case it's a custom, local-only installation. */
184             Log(LOG_LEVEL_VERBOSE,
185                 "Couldn't find a private key at '%s', use cf-key to get one. (fopen: %s)",
186                 privkeyfile != NULL ? privkeyfile : priv_key_path, GetErrorStr());
187             free(privkeyfile);
188             return false;
189         }
190 
191         if (priv_key == NULL)
192         {
193             /* if no place to store the private key was specified, use the
194              * global variable PRIVKEY */
195             priv_key = &PRIVKEY;
196         }
197         if (*priv_key != NULL)
198         {
199             DESTROY_AND_NULL(RSA_free, *priv_key);
200         }
201 
202         // Can read both encrypted (old) and unencrypted(new) key files:
203         *priv_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, (void*) priv_passphrase);
204         if (*priv_key == NULL)
205         {
206             Log(LOG_LEVEL_ERR,
207                 "Error reading private key. (PEM_read_RSAPrivateKey: %s)",
208                 CryptoLastErrorString());
209             *priv_key = NULL;
210             fclose(fp);
211             return false;
212         }
213 
214         fclose(fp);
215         Log(LOG_LEVEL_VERBOSE, "Loaded private key at '%s'", privkeyfile);
216         free(privkeyfile);
217     }
218 
219     {
220         char *pubkeyfile = NULL;
221         if (pub_key_path == NULL)
222         {
223             pubkeyfile = PublicKeyFile(GetWorkDir());
224         }
225         FILE *fp = safe_fopen(pubkeyfile != NULL ? pubkeyfile : pub_key_path, "r");
226         if (!fp)
227         {
228             /* VERBOSE in case it's a custom, local-only installation. */
229             Log(LOG_LEVEL_VERBOSE,
230                 "Couldn't find a public key at '%s', use cf-key to get one (fopen: %s)",
231                 pubkeyfile != NULL ? pubkeyfile : pub_key_path, GetErrorStr());
232             free(pubkeyfile);
233             return false;
234         }
235 
236         if (pub_key == NULL)
237         {
238             /* if no place to store the public key was specified, use the
239              * global variable PUBKEY */
240             pub_key = &PUBKEY;
241         }
242         if (*pub_key != NULL)
243         {
244             DESTROY_AND_NULL(RSA_free, *pub_key);
245         }
246         *pub_key = PEM_read_RSAPublicKey(fp, NULL, NULL, (void*) priv_passphrase);
247         if (*pub_key == NULL)
248         {
249             Log(LOG_LEVEL_ERR,
250                 "Error reading public key at '%s'. (PEM_read_RSAPublicKey: %s)",
251                 pubkeyfile, CryptoLastErrorString());
252             fclose(fp);
253             free(pubkeyfile);
254             return false;
255         }
256 
257         Log(LOG_LEVEL_VERBOSE, "Loaded public key '%s'", pubkeyfile);
258         free(pubkeyfile);
259         fclose(fp);
260     }
261 
262     if (*pub_key != NULL)
263     {
264         const BIGNUM *n, *e;
265         RSA_get0_key(*pub_key, &n, &e, NULL);
266         if ((BN_num_bits(e) < 2) || (!BN_is_odd(e)))
267         {
268             Log(LOG_LEVEL_ERR, "The public key RSA exponent is too small or not odd");
269             return false;
270         }
271     }
272 
273     return true;
274 }
275 
PolicyHubUpdateKeys(const char * policy_server)276 void PolicyHubUpdateKeys(const char *policy_server)
277 {
278     if (GetAmPolicyHub() && PUBKEY != NULL)
279     {
280         unsigned char digest[EVP_MAX_MD_SIZE + 1];
281         const char* const workdir = GetWorkDir();
282 
283         char dst_public_key_filename[CF_BUFSIZE] = "";
284         {
285             char buffer[CF_HOSTKEY_STRING_SIZE];
286             HashPubKey(PUBKEY, digest, CF_DEFAULT_DIGEST);
287             snprintf(dst_public_key_filename, sizeof(dst_public_key_filename),
288                      "%s/ppkeys/%s-%s.pub",
289                      workdir, "root",
290                      HashPrintSafe(buffer, sizeof(buffer), digest,
291                                    CF_DEFAULT_DIGEST, true));
292             MapName(dst_public_key_filename);
293         }
294 
295         struct stat sb;
296         if ((stat(dst_public_key_filename, &sb) == -1))
297         {
298             char src_public_key_filename[CF_BUFSIZE] = "";
299             snprintf(src_public_key_filename, CF_MAXVARSIZE, "%s/ppkeys/localhost.pub", workdir);
300             MapName(src_public_key_filename);
301 
302             // copy localhost.pub to root-HASH.pub on policy server
303             if (!LinkOrCopy(src_public_key_filename, dst_public_key_filename, false))
304             {
305                 Log(LOG_LEVEL_ERR, "Unable to copy policy server's own public key from '%s' to '%s'", src_public_key_filename, dst_public_key_filename);
306             }
307 
308             if (policy_server)
309             {
310                 LastSaw(policy_server, digest, LAST_SEEN_ROLE_CONNECT);
311             }
312         }
313     }
314 }
315 
316 /*********************************************************************/
317 
318 /**
319  * @brief Search for a key given an IP address, by getting the
320  *        key hash value from lastseen db.
321  * @return NULL if the key was not found in any form.
322  */
HavePublicKeyByIP(const char * username,const char * ipaddress)323 RSA *HavePublicKeyByIP(const char *username, const char *ipaddress)
324 {
325     char hash[CF_HOSTKEY_STRING_SIZE];
326 
327     /* Get the key hash for that address from lastseen db. */
328     bool found = Address2Hostkey(hash, sizeof(hash), ipaddress);
329 
330     /* If not found, by passing "" as digest, we effectively look only for
331      * the old-style key file, e.g. root-1.2.3.4.pub. */
332     return HavePublicKey(username, ipaddress,
333                          found ? hash : "");
334 }
335 
336 static const char *const pub_passphrase = "public";
337 
338 /**
339  * @brief Search for a key:
340  *        1. username-hash.pub
341  *        2. username-ip.pub
342  * @return NULL if key not found in any form
343  */
HavePublicKey(const char * username,const char * ipaddress,const char * digest)344 RSA *HavePublicKey(const char *username, const char *ipaddress, const char *digest)
345 {
346     char keyname[CF_MAXVARSIZE], newname[CF_BUFSIZE], oldname[CF_BUFSIZE];
347     struct stat statbuf;
348     RSA *newkey = NULL;
349     const char* const workdir = GetWorkDir();
350 
351     snprintf(keyname, CF_MAXVARSIZE, "%s-%s", username, digest);
352 
353     snprintf(newname, CF_BUFSIZE, "%s/ppkeys/%s.pub", workdir, keyname);
354     MapName(newname);
355 
356     if (stat(newname, &statbuf) == -1)
357     {
358         Log(LOG_LEVEL_VERBOSE, "Did not find new key format '%s'", newname);
359 
360         snprintf(oldname, CF_BUFSIZE, "%s/ppkeys/%s-%s.pub",
361                  workdir, username, ipaddress);
362         MapName(oldname);
363         Log(LOG_LEVEL_VERBOSE, "Trying old style '%s'", oldname);
364 
365         if (stat(oldname, &statbuf) == -1)
366         {
367             Log(LOG_LEVEL_DEBUG, "Did not have old-style key '%s'", oldname);
368             return NULL;
369         }
370 
371         if (strlen(digest) > 0)
372         {
373             Log(LOG_LEVEL_INFO, "Renaming old key from '%s' to '%s'", oldname, newname);
374 
375             if (rename(oldname, newname) != 0)
376             {
377                 Log(LOG_LEVEL_ERR, "Could not rename from old key format '%s' to new '%s'. (rename: %s)", oldname, newname, GetErrorStr());
378             }
379         }
380         else
381         {
382             /* We don't know the digest (e.g. because we are a client and have
383                no lastseen-map yet), so we're using old file format
384                (root-IP.pub). */
385             Log(LOG_LEVEL_VERBOSE,
386                 "We have no digest yet, using old keyfile name: %s",
387                 oldname);
388             snprintf(newname, sizeof(newname), "%s", oldname);
389         }
390     }
391 
392     FILE *fp = safe_fopen(newname, "r");
393     if (fp == NULL)
394     {
395         Log(LOG_LEVEL_ERR, "Couldn't open public key file '%s' (fopen: %s)",
396             newname, GetErrorStr());
397         return NULL;
398     }
399 
400     if ((newkey = PEM_read_RSAPublicKey(fp, NULL, NULL,
401                                         (void *)pub_passphrase)) == NULL)
402     {
403         Log(LOG_LEVEL_ERR,
404             "Error reading public key from '%s' (PEM_read_RSAPublicKey: %s)",
405             newname, CryptoLastErrorString());
406         fclose(fp);
407         return NULL;
408     }
409 
410     fclose(fp);
411 
412     {
413         const BIGNUM *n, *e;
414         RSA_get0_key(newkey, &n, &e, NULL);
415         if ((BN_num_bits(e) < 2) || (!BN_is_odd(e)))
416         {
417             Log(LOG_LEVEL_ERR, "RSA Exponent too small or not odd for key: %s",
418                 newname);
419             RSA_free(newkey);
420             return NULL;
421         }
422     }
423 
424     return newkey;
425 }
426 
427 /*********************************************************************/
428 
SavePublicKey(const char * user,const char * digest,const RSA * key)429 bool SavePublicKey(const char *user, const char *digest, const RSA *key)
430 {
431     char keyname[CF_MAXVARSIZE], filename[CF_BUFSIZE];
432     struct stat statbuf;
433     int ret;
434 
435     ret = snprintf(keyname, sizeof(keyname), "%s-%s", user, digest);
436     if (ret < 0)
437     {
438         Log(LOG_LEVEL_ERR, "snprintf failed: %s", GetErrorStr());
439         return false;
440     }
441     else if ((unsigned long) ret >= sizeof(keyname))
442     {
443         Log(LOG_LEVEL_ERR, "USERNAME-KEY (%s-%s) string too long!",
444             user, digest);
445         return false;
446     }
447 
448     ret = snprintf(filename, sizeof(filename), "%s/ppkeys/%s.pub",
449                    GetWorkDir(), keyname);
450     if (ret < 0)
451     {
452         Log(LOG_LEVEL_ERR, "snprintf failed: %s", GetErrorStr());
453         return false;
454     }
455     else if ((unsigned long) ret >= sizeof(filename))
456     {
457         Log(LOG_LEVEL_ERR, "Filename too long!");
458         return false;
459     }
460 
461     MapName(filename);
462     if (stat(filename, &statbuf) != -1)
463     {
464         Log(LOG_LEVEL_VERBOSE,
465             "Public key file '%s' already exists, not rewriting",
466             filename);
467         return true;
468     }
469 
470     Log(LOG_LEVEL_VERBOSE, "Saving public key to file '%s'", filename);
471 
472     FILE *fp = safe_fopen_create_perms(filename, "w", CF_PERMS_DEFAULT);
473     if (fp == NULL)
474     {
475         Log(LOG_LEVEL_ERR, "Unable to write a public key '%s'. (fopen: %s)", filename, GetErrorStr());
476         return false;
477     }
478 
479     if (!PEM_write_RSAPublicKey(fp, key))
480     {
481         Log(LOG_LEVEL_ERR,
482             "Error saving public key to '%s'. (PEM_write_RSAPublicKey: %s)",
483             filename, CryptoLastErrorString());
484         fclose(fp);
485         return false;
486     }
487 
488     fclose(fp);
489     return true;
490 }
491 
LoadPublicKey(const char * filename)492 RSA *LoadPublicKey(const char *filename)
493 {
494     FILE *fp;
495     RSA *key;
496     const BIGNUM *n, *e;
497 
498     fp = safe_fopen(filename, "r");
499     if (fp == NULL)
500     {
501         Log(LOG_LEVEL_ERR, "Cannot open public key file '%s' (fopen: %s)", filename, GetErrorStr());
502         return NULL;
503     };
504 
505     if ((key = PEM_read_RSAPublicKey(fp, NULL, NULL,
506                                      (void *)priv_passphrase)) == NULL)
507     {
508         Log(LOG_LEVEL_ERR,
509             "Error while reading public key '%s' (PEM_read_RSAPublicKey: %s)",
510             filename,
511             CryptoLastErrorString());
512         fclose(fp);
513         return NULL;
514     };
515 
516     fclose(fp);
517 
518     RSA_get0_key(key, &n, &e, NULL);
519 
520     if (BN_num_bits(e) < 2 || !BN_is_odd(e))
521     {
522         Log(LOG_LEVEL_ERR, "Error while reading public key '%s' - RSA Exponent is too small or not odd. (BN_num_bits: %s)",
523             filename, GetErrorStr());
524         return NULL;
525     };
526 
527     return key;
528 }
529 
530 /** Return a string with the printed digest of the given key file,
531     or NULL if an error occurred. */
LoadPubkeyDigest(const char * filename)532 char *LoadPubkeyDigest(const char *filename)
533 {
534     unsigned char digest[EVP_MAX_MD_SIZE + 1];
535     RSA *key = NULL;
536     char *buffer = xmalloc(CF_HOSTKEY_STRING_SIZE);
537 
538     key = LoadPublicKey(filename);
539     if (key == NULL)
540     {
541         return NULL;
542     }
543 
544     HashPubKey(key, digest, CF_DEFAULT_DIGEST);
545     HashPrintSafe(buffer, CF_HOSTKEY_STRING_SIZE,
546                   digest, CF_DEFAULT_DIGEST, true);
547     RSA_free(key);
548     return buffer;
549 }
550 
551 /** Return a string with the printed digest of the given key file. */
GetPubkeyDigest(RSA * pubkey)552 char *GetPubkeyDigest(RSA *pubkey)
553 {
554     unsigned char digest[EVP_MAX_MD_SIZE + 1];
555     char *buffer = xmalloc(CF_HOSTKEY_STRING_SIZE);
556 
557     HashPubKey(pubkey, digest, CF_DEFAULT_DIGEST);
558     HashPrintSafe(buffer, CF_HOSTKEY_STRING_SIZE,
559                   digest, CF_DEFAULT_DIGEST, true);
560     return buffer;
561 }
562 
563 
564 /**
565  * Trust the given key.  If #ipaddress is not NULL, then also
566  * update the "last seen" database.  The IP address is required for
567  * trusting a server key (on the client); it is -currently- optional
568  * for trusting a client key (on the server).
569  */
TrustKey(const char * filename,const char * ipaddress,const char * username)570 bool TrustKey(const char *filename, const char *ipaddress, const char *username)
571 {
572     RSA* key;
573     char *digest;
574 
575     key = LoadPublicKey(filename);
576     if (key == NULL)
577     {
578         return false;
579     }
580 
581     digest = GetPubkeyDigest(key);
582     if (digest == NULL)
583     {
584         RSA_free(key);
585         return false;
586     }
587 
588     if (ipaddress != NULL)
589     {
590         Log(LOG_LEVEL_VERBOSE,
591             "Adding a CONNECT entry in lastseen db: IP '%s', key '%s'",
592             ipaddress, digest);
593         LastSaw1(ipaddress, digest, LAST_SEEN_ROLE_CONNECT);
594     }
595 
596     bool ret = SavePublicKey(username, digest, key);
597     RSA_free(key);
598     free(digest);
599 
600     return ret;
601 }
602 
EncryptString(char * out,size_t out_size,const char * in,int plainlen,char type,unsigned char * key)603 int EncryptString(char *out, size_t out_size, const char *in, int plainlen,
604                   char type, unsigned char *key)
605 {
606     int cipherlen = 0, tmplen;
607     unsigned char iv[32] =
608         { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 };
609 
610     if (key == NULL)
611         ProgrammingError("EncryptString: session key == NULL");
612 
613     size_t max_ciphertext_size = CipherTextSizeMax(CfengineCipher(type), plainlen);
614 
615     if(max_ciphertext_size > out_size)
616     {
617         ProgrammingError("EncryptString: output buffer too small: max_ciphertext_size (%zd) > out_size (%zd)",
618                           max_ciphertext_size, out_size);
619     }
620 
621     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
622     EVP_EncryptInit_ex(ctx, CfengineCipher(type), NULL, key, iv);
623 
624     if (!EVP_EncryptUpdate(ctx, out, &cipherlen, in, plainlen))
625     {
626         EVP_CIPHER_CTX_free(ctx);
627         return -1;
628     }
629 
630     if (!EVP_EncryptFinal_ex(ctx, out + cipherlen, &tmplen))
631     {
632         EVP_CIPHER_CTX_free(ctx);
633         return -1;
634     }
635 
636     cipherlen += tmplen;
637 
638     if (cipherlen < 0)
639     {
640         ProgrammingError("EncryptString: chipherlen (%d) < 0", cipherlen);
641     }
642     else if ((size_t) cipherlen > max_ciphertext_size)
643     {
644         ProgrammingError("EncryptString: too large ciphertext written: cipherlen (%d) > max_ciphertext_size (%zd)",
645                           cipherlen, max_ciphertext_size);
646     }
647 
648     EVP_CIPHER_CTX_free(ctx);
649     return cipherlen;
650 }
651 
CipherBlockSizeBytes(const EVP_CIPHER * cipher)652 size_t CipherBlockSizeBytes(const EVP_CIPHER *cipher)
653 {
654     return EVP_CIPHER_block_size(cipher);
655 }
656 
CipherTextSizeMax(const EVP_CIPHER * cipher,size_t plaintext_size)657 size_t CipherTextSizeMax(const EVP_CIPHER* cipher, size_t plaintext_size)
658 {
659     // see man EVP_DecryptUpdate() and EVP_DecryptFinal_ex()
660     size_t padding_size = (CipherBlockSizeBytes(cipher) * 2) - 1;
661 
662     // check for potential integer overflow, leave some buffer
663     if(plaintext_size > SIZE_MAX - padding_size)
664     {
665         ProgrammingError("CipherTextSizeMax: plaintext_size is too large (%zu)",
666                          plaintext_size);
667     }
668 
669     return plaintext_size + padding_size;
670 }
671 
PlainTextSizeMax(const EVP_CIPHER * cipher,size_t ciphertext_size)672 size_t PlainTextSizeMax(const EVP_CIPHER* cipher, size_t ciphertext_size)
673 {
674     // see man EVP_DecryptUpdate() and EVP_DecryptFinal_ex()
675     size_t padding_size = (CipherBlockSizeBytes(cipher) * 2);
676 
677     // check for potential integer overflow, leave some buffer
678     if(ciphertext_size > SIZE_MAX - padding_size)
679     {
680         ProgrammingError("PlainTextSizeMax: ciphertext_size is too large (%zu)",
681                          ciphertext_size);
682     }
683 
684     return ciphertext_size + padding_size;
685 }
686 
687 /*********************************************************************/
688 
DecryptString(char * out,size_t out_size,const char * in,int cipherlen,char type,unsigned char * key)689 int DecryptString(char *out, size_t out_size, const char *in, int cipherlen,
690                   char type, unsigned char *key)
691 {
692     int plainlen = 0, tmplen;
693     unsigned char iv[32] =
694         { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 };
695 
696     if (key == NULL)
697         ProgrammingError("DecryptString: session key == NULL");
698 
699     size_t max_plaintext_size = PlainTextSizeMax(CfengineCipher(type), cipherlen);
700 
701     if(max_plaintext_size > out_size)
702     {
703         ProgrammingError("DecryptString: output buffer too small: max_plaintext_size (%zd) > out_size (%zd)",
704                           max_plaintext_size, out_size);
705     }
706 
707     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
708     EVP_DecryptInit_ex(ctx, CfengineCipher(type), NULL, key, iv);
709 
710     if (!EVP_DecryptUpdate(ctx, out, &plainlen, in, cipherlen))
711     {
712         Log(LOG_LEVEL_ERR, "Failed to decrypt string");
713         EVP_CIPHER_CTX_free(ctx);
714         return -1;
715     }
716 
717     if (!EVP_DecryptFinal_ex(ctx, out + plainlen, &tmplen))
718     {
719         unsigned long err = ERR_get_error();
720 
721         Log(LOG_LEVEL_ERR, "Failed to decrypt at final of cipher length %d. (EVP_DecryptFinal_ex: %s)", cipherlen, ERR_error_string(err, NULL));
722         EVP_CIPHER_CTX_free(ctx);
723         return -1;
724     }
725 
726     plainlen += tmplen;
727 
728     if (plainlen < 0)
729     {
730         ProgrammingError("DecryptString: plainlen (%d) < 0", plainlen);
731     }
732     if ((size_t) plainlen > max_plaintext_size)
733     {
734         ProgrammingError("DecryptString: too large plaintext written: plainlen (%d) > max_plaintext_size (%zd)",
735                           plainlen, max_plaintext_size);
736     }
737 
738     EVP_CIPHER_CTX_free(ctx);
739     return plainlen;
740 }
741 
742 /*********************************************************************/
743 
DebugBinOut(char * buffer,int len,char * comment)744 void DebugBinOut(char *buffer, int len, char *comment)
745 {
746     unsigned char *sp;
747     char buf[CF_BUFSIZE];
748     char hexStr[3];             // one byte as hex
749 
750     if (len < 0)
751     {
752         Log(LOG_LEVEL_ERR, "Debug binary print negative len param (len = %d)", len);
753     }
754     else if ((unsigned long) len >= (sizeof(buf) / 2))       // hex uses two chars per byte
755     {
756         Log(LOG_LEVEL_DEBUG, "Debug binary print is too large (len = %d)", len);
757         return;
758     }
759 
760     memset(buf, 0, sizeof(buf));
761 
762     for (sp = buffer; sp < (unsigned char *) (buffer + len); sp++)
763     {
764         xsnprintf(hexStr, sizeof(hexStr), "%2.2x", (int) *sp);
765         strcat(buf, hexStr);
766     }
767 
768     Log(LOG_LEVEL_VERBOSE, "BinaryBuffer, %d bytes, comment '%s', buffer '%s'", len, comment, buf);
769 }
770 
PublicKeyFile(const char * workdir)771 char *PublicKeyFile(const char *workdir)
772 {
773     char *keyfile;
774     xasprintf(&keyfile,
775               "%s" FILE_SEPARATOR_STR "ppkeys" FILE_SEPARATOR_STR "localhost.pub", workdir);
776     return keyfile;
777 }
778 
PrivateKeyFile(const char * workdir)779 char *PrivateKeyFile(const char *workdir)
780 {
781     char *keyfile;
782     xasprintf(&keyfile,
783               "%s" FILE_SEPARATOR_STR "ppkeys" FILE_SEPARATOR_STR "localhost.priv", workdir);
784     return keyfile;
785 }
786 
787 
788 /*********************************************************************
789  * Functions for threadsafe OpenSSL usage                            *
790  * Only pthread support - we don't create threads with any other API *
791  *********************************************************************/
792 
793 static pthread_mutex_t *cf_openssl_locks = NULL;
794 
795 
796 #ifndef __MINGW32__
797 #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(LIBRESSL_VERSION_NUMBER)
ThreadId_callback(void)798 unsigned long ThreadId_callback(void)
799 {
800     return (unsigned long) pthread_self();
801 }
802 #endif
803 #endif
804 
805 #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(LIBRESSL_VERSION_NUMBER)
806 
OpenSSLLock_callback(int mode,int index,char * file,int line)807 static void OpenSSLLock_callback(int mode, int index, char *file, int line)
808 {
809     if (mode & CRYPTO_LOCK)
810     {
811         int ret = pthread_mutex_lock(&(cf_openssl_locks[index]));
812         if (ret != 0)
813         {
814             Log(LOG_LEVEL_ERR,
815                 "OpenSSL locking failure at %s:%d! (pthread_mutex_lock: %s)",
816                 file, line, GetErrorStrFromCode(ret));
817         }
818     }
819     else
820     {
821         int ret = pthread_mutex_unlock(&(cf_openssl_locks[index]));
822         if (ret != 0)
823         {
824             Log(LOG_LEVEL_ERR,
825                 "OpenSSL locking failure at %s:%d! (pthread_mutex_unlock: %s)",
826                 file, line, GetErrorStrFromCode(ret));
827         }
828     }
829 }
830 
831 #endif // Callback only for openssl < 1.1.0
832 
SetupOpenSSLThreadLocks(void)833 static void SetupOpenSSLThreadLocks(void)
834 {
835     const int num_locks = CRYPTO_num_locks();
836     assert(cf_openssl_locks == NULL);
837     cf_openssl_locks = xmalloc(num_locks * sizeof(*cf_openssl_locks));
838 
839     for (int i = 0; i < num_locks; i++)
840     {
841         pthread_mutexattr_t attr;
842         pthread_mutexattr_init(&attr);
843         int ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
844         if (ret != 0)
845         {
846             Log(LOG_LEVEL_ERR,
847                 "Failed to use error-checking mutexes for openssl,"
848                 " falling back to normal ones (pthread_mutexattr_settype: %s)",
849                 GetErrorStrFromCode(ret));
850             pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
851         }
852         ret = pthread_mutex_init(&cf_openssl_locks[i], &attr);
853         if (ret != 0)
854         {
855             Log(LOG_LEVEL_CRIT,
856                 "Failed to use initialise mutexes for openssl"
857                 " (pthread_mutex_init: %s)!",
858                 GetErrorStrFromCode(ret));
859         }
860         pthread_mutexattr_destroy(&attr);
861     }
862 
863 #ifndef __MINGW32__
864     CRYPTO_set_id_callback((unsigned long (*)())ThreadId_callback);
865 #endif
866     // This is a no-op macro for OpenSSL >= 1.1.0
867     // The callback function is not used (or defined) then
868     CRYPTO_set_locking_callback((void (*)())OpenSSLLock_callback);
869 }
870 
CleanupOpenSSLThreadLocks(void)871 static void CleanupOpenSSLThreadLocks(void)
872 {
873     const int numLocks = CRYPTO_num_locks();
874     CRYPTO_set_locking_callback(NULL);
875 #ifndef __MINGW32__
876     CRYPTO_set_id_callback(NULL);
877 #endif
878 
879     for (int i = 0; i < numLocks; i++)
880     {
881         pthread_mutex_destroy(&(cf_openssl_locks[i]));
882     }
883 
884     free(cf_openssl_locks);
885     cf_openssl_locks = NULL;
886 }
887