/** * @return true the error is not so severe that we must stop */ bool LoadSecretKeys(void) { { char *privkeyfile = PrivateKeyFile(GetWorkDir()); FILE *fp = fopen(privkeyfile, "r"); if (!fp) { Log(CryptoGetMissingKeyLogLevel(), "Couldn't find a private key at '%s', use cgn-key to get one. (fopen: %s)", privkeyfile, GetErrorStr()); free(privkeyfile); return false; } PRIVKEY = PEM_read_RSAPrivateKey(fp, NULL, NULL, (void*) priv_passphrase); if (PRIVKEY == NULL) { Log(LOG_LEVEL_VERBOSE, "Error reading private key. (PEM_read_RSAPrivateKey: %s)", CryptoLastErrorString()); PRIVKEY = NULL; fclose(fp); return false; } fclose(fp); Log(LOG_LEVEL_VERBOSE, "Loaded private key at '%s'", privkeyfile); free(privkeyfile); } { char *pubkeyfile = PublicKeyFile(GetWorkDir()); FILE *fp = fopen(pubkeyfile, "r"); if (!fp) { Log(CryptoGetMissingKeyLogLevel(), "Couldn't find a public key at '%s', use cgn-key to get one (fopen: %s)", pubkeyfile, GetErrorStr()); free(pubkeyfile); return false; } PUBKEY = PEM_read_RSAPublicKey(fp, NULL, NULL, (void*) priv_passphrase); if (NULL == PUBKEY) { Log(LOG_LEVEL_ERR, "Error reading public key at '%s'. (PEM_read_RSAPublicKey: %s)", pubkeyfile, CryptoLastErrorString()); fclose(fp); free(pubkeyfile); return false; } Log(LOG_LEVEL_VERBOSE, "Loaded public key '%s'", pubkeyfile); free(pubkeyfile); fclose(fp); } if (NULL != PUBKEY && ((BN_num_bits(PUBKEY->e) < 2) || (!BN_is_odd(PUBKEY->e)))) { Log(LOG_LEVEL_ERR, "The public key RSA exponent is too small or not odd"); return false; } return true; }
/** * @brief Search for a key: * 1. username-hash.pub * 2. username-ip.pub * @return NULL if key not found in any form */ RSA *HavePublicKey(const char *username, const char *ipaddress, const char *digest) { char keyname[CF_MAXVARSIZE], newname[CF_BUFSIZE], oldname[CF_BUFSIZE]; struct stat statbuf; FILE *fp; RSA *newkey = NULL; snprintf(keyname, CF_MAXVARSIZE, "%s-%s", username, digest); snprintf(newname, CF_BUFSIZE, "%s/ppkeys/%s.pub", CFWORKDIR, keyname); MapName(newname); if (stat(newname, &statbuf) == -1) { Log(LOG_LEVEL_VERBOSE, "Did not find new key format '%s'", newname); snprintf(oldname, CF_BUFSIZE, "%s/ppkeys/%s-%s.pub", CFWORKDIR, username, ipaddress); MapName(oldname); Log(LOG_LEVEL_VERBOSE, "Trying old style '%s'", oldname); if (stat(oldname, &statbuf) == -1) { Log(LOG_LEVEL_DEBUG, "Did not have old-style key '%s'", oldname); return NULL; } if (strlen(digest) > 0) { Log(LOG_LEVEL_INFO, "Renaming old key from '%s' to '%s'", oldname, newname); if (rename(oldname, newname) != 0) { Log(LOG_LEVEL_ERR, "Could not rename from old key format '%s' to new '%s'. (rename: %s)", oldname, newname, GetErrorStr()); } } else { /* We don't know the digest (e.g. because we are a client and have no lastseen-map yet), so we're using old file format (root-IP.pub). */ Log(LOG_LEVEL_VERBOSE, "We have no digest yet, using old keyfile name: %s", oldname); snprintf(newname, sizeof(newname), "%s", oldname); } } if ((fp = fopen(newname, "r")) == NULL) { Log(CryptoGetMissingKeyLogLevel(), "Couldn't find a public key '%s'. (fopen: %s)", newname, GetErrorStr()); return NULL; } if ((newkey = PEM_read_RSAPublicKey(fp, NULL, NULL, (void *)pub_passphrase)) == NULL) { Log(LOG_LEVEL_ERR, "Error reading public key. (PEM_read_RSAPublicKey: %s)", CryptoLastErrorString()); fclose(fp); return NULL; } fclose(fp); if ((BN_num_bits(newkey->e) < 2) || (!BN_is_odd(newkey->e))) { Log(LOG_LEVEL_ERR, "RSA Exponent too small or not odd"); RSA_free(newkey); return NULL; } return newkey; }
/** * @warning Make sure you've called CryptoInitialize() first! */ bool TLSClientInitialize() { int ret; static bool is_initialised = false; if (is_initialised) { return true; } if (!TLSGenericInitialize()) { return false; } SSLCLIENTCONTEXT = SSL_CTX_new(SSLv23_client_method()); if (SSLCLIENTCONTEXT == NULL) { Log(LOG_LEVEL_ERR, "SSL_CTX_new: %s", ERR_reason_error_string(ERR_get_error())); goto err1; } TLSSetDefaultOptions(SSLCLIENTCONTEXT); if (PRIVKEY == NULL || PUBKEY == NULL) { Log(CryptoGetMissingKeyLogLevel(), "No public/private key pair is loaded, trying to reload"); LoadSecretKeys(); if (PRIVKEY == NULL || PUBKEY == NULL) { Log(CryptoGetMissingKeyLogLevel(), "No public/private key pair found"); goto err2; } } /* Create cert into memory and load it into SSL context. */ SSLCLIENTCERT = TLSGenerateCertFromPrivKey(PRIVKEY); if (SSLCLIENTCERT == NULL) { Log(LOG_LEVEL_ERR, "Failed to generate in-memory-certificate from private key"); goto err2; } SSL_CTX_use_certificate(SSLCLIENTCONTEXT, SSLCLIENTCERT); ret = SSL_CTX_use_RSAPrivateKey(SSLCLIENTCONTEXT, PRIVKEY); if (ret != 1) { Log(LOG_LEVEL_ERR, "Failed to use RSA private key: %s", ERR_reason_error_string(ERR_get_error())); goto err3; } /* Verify cert consistency. */ ret = SSL_CTX_check_private_key(SSLCLIENTCONTEXT); if (ret != 1) { Log(LOG_LEVEL_ERR, "Inconsistent key and TLS cert: %s", ERR_reason_error_string(ERR_get_error())); goto err3; } is_initialised = true; return true; err3: X509_free(SSLCLIENTCERT); SSLCLIENTCERT = NULL; err2: SSL_CTX_free(SSLCLIENTCONTEXT); SSLCLIENTCONTEXT = NULL; err1: return false; }