How to upload a PEM format certificate like x509 in opensl C ++?
You should SSL_CTX_use_certificate_chain_file use SSL_CTX_use_certificate_chain_file and SSL_CTX_use_PrivateKey_file . You can use them and create a client or server context. An example code is shown below. There are several nuances of their use, so check out the OpenSSL documentation on SSL_CTX_use_certificate(3) .
I'm not sure what βlike x509β means. The certificate will be x509, but the private key will be PKCS # 8. There are PEM_read_bio_X509 and PEM_read_X509 , they return X509* , and they can do what you want.
Will SSL_CTX_set_default_passwd_cb work with the private keys that I upload
It depends, but he must. Password callback is optional. Use it if the password is protected by a key. In the code below, I call it PasswordCallback , and it is used to read and write the key (read only is shown below).
using SSL_CTX_ptr = std::unique_ptr<SSL_CTX, decltype(&::SSL_CTX_free)>; SSL_CTX* CreateServerContext() { do { int rc; unsigned long err; const SSL_METHOD* method = SSLv23_server_method(); ASSERT(method != NULL); if (method == NULL) { LogError("GetServerContext: SSLv23_server_method failed"); break; } SSL_CTX_ptr t(SSL_CTX_new(method), ::SSL_CTX_free); ASSERT(t.get() != NULL); if (t.get() == NULL) { LogError("GetServerContext: SSL_CTX_new failed"); break; } long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; flags |= SSL_OP_NO_COMPRESSION; flags |= SSL_OP_SAFARI_ECDHE_ECDSA_BUG; flags |= SSL_OP_CIPHER_SERVER_PREFERENCE; SSL_CTX_set_options(t.get(), flags); string ciphers = GetServerCipherSuites(); ASSERT(!ciphers.empty()); rc = SSL_CTX_set_cipher_list(t.get(), ciphers.c_str()); err = ERR_get_error(); ASSERT(rc == 1); if (rc != 1) { LogError("GetServerContext: SSL_CTX_set_cipher_list failed"); break; } string certFile = config.GetServerCertFile(); ASSERT(!certFile.empty()); rc = SSL_CTX_use_certificate_chain_file(t.get(), certFile.c_str()); err = ERR_get_error(); ASSERT(rc == 1); if (rc != 1) { LogError("GetServerContext: SSL_CTX_use_certificate_chain_file failed"); break; } SSL_CTX_set_default_passwd_cb(t.get(), PasswordCallback); SSL_CTX_set_default_passwd_cb_userdata(t.get(), (void*) SERVER_KEY_LABEL); string keyFile = config.GetServerKeyFile(); ASSERT(!keyFile.empty()); rc = SSL_CTX_use_PrivateKey_file(t.get(), keyFile.c_str(), SSL_FILETYPE_PEM); err = ERR_get_error(); ASSERT(rc == 1); if (rc != 1) { LogError("GetServerContext: SSL_CTX_use_PrivateKey_file failed"); break; } rc = SSL_CTX_check_private_key(t.get()); err = ERR_get_error(); ASSERT(rc == 1); if (rc != 1) { LogError("GetServerContext: SSL_CTX_check_private_key failed"); } SSL_CTX_set_tmp_dh_callback(t.get(), DhCallback); SSL_CTX_set_tmp_ecdh_callback(t.get(), EcdhCallback); SSL_CTX_set_tlsext_servername_callback(t.get(), ServerNameCallback); return t.release(); } while (0); return NULL; }
Password callback idea: OpenSSL provides you with a buffer and size. You fill the buffer and return the size of how much you filled.
My password callback is somewhat involved. It executes one hash of the raw password before passing it to the library. This ensures that the βplain textβ password is not used (but does not slow down normal attacks). Yours may request a string from the user or may return a string encoded string.
My callback uses a label. The shortcut allows me to get different keys depending on the use (although the same "base secret" is used). By specifying a different usage or label, I get a different key output. The label is provided via arg below, and you can set it using SSL_CTX_set_default_passwd_cb_userdata .
using EVP_MD_CTX_ptr = std::unique_ptr<EVP_MD_CTX, decltype(&::EVP_MD_CTX_destroy)>; int PasswordCallback(char *buffer, int size, int rwflag, void *arg) { UNUSED(rwflag); int rc; unsigned long err; ostringstream oss; const char* label = (char*) arg; size_t lsize = (label ? strlen(label) : 0); SecureVector sv = config.GetMasterKey(); AC_ASSERT(!sv.empty()); if (sv.empty()) { ... throw runtime_error(oss.str().c_str()); } EVP_MD_CTX_ptr ctx(EVP_MD_CTX_create(), ::EVP_MD_CTX_destroy); AC_ASSERT(ctx.get() != NULL); const EVP_MD* hash = EVP_sha512(); AC_ASSERT(hash != NULL); rc = EVP_DigestInit_ex(ctx.get(), hash, NULL); err = ERR_get_error(); AC_ASSERT(rc == 1); if (rc != 1) { ... throw runtime_error(oss.str().c_str()); } rc = EVP_DigestUpdate(ctx.get(), sv.data(), sv.size()); err = ERR_get_error(); AC_ASSERT(rc == 1); if (rc != 1) { ... throw runtime_error(oss.str().c_str()); } if (label && lsize) { rc = EVP_DigestUpdate(ctx.get(), label, lsize); err = ERR_get_error(); AC_ASSERT(rc == 1); if (rc != 1) { ... throw runtime_error(oss.str().c_str()); } } int n = std::min(size, EVP_MD_size(hash)); if (n <= 0) return 0; rc = EVP_DigestFinal_ex(ctx.get(), (unsigned char*) buffer, (unsigned int*) &n); err = ERR_get_error(); AC_ASSERT(rc == 1); if (rc != 1) { ... throw runtime_error(oss.str().c_str()); } return n; }