PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG(int pbe_nid, const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8) { PKCS12_SAFEBAG *bag; const EVP_CIPHER *pbe_ciph; /* Set up the safe bag */ if (!(bag = PKCS12_SAFEBAG_new())) { PKCS12err(PKCS12_F_PKCS12_MAKE_SHKEYBAG, ERR_R_MALLOC_FAILURE); return NULL; } bag->type = OBJ_nid2obj(NID_pkcs8ShroudedKeyBag); pbe_ciph = EVP_get_cipherbynid(pbe_nid); if (pbe_ciph) pbe_nid = -1; if (!(bag->value.shkeybag = PKCS8_encrypt(pbe_nid, pbe_ciph, pass, passlen, salt, saltlen, iter, p8))) { PKCS12err(PKCS12_F_PKCS12_MAKE_SHKEYBAG, ERR_R_MALLOC_FAILURE); return NULL; } return bag; }
PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid, const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8inf) { PKCS12_SAFEBAG *bag; const EVP_CIPHER *pbe_ciph; X509_SIG *p8; pbe_ciph = EVP_get_cipherbynid(pbe_nid); if (pbe_ciph) pbe_nid = -1; p8 = PKCS8_encrypt(pbe_nid, pbe_ciph, pass, passlen, salt, saltlen, iter, p8inf); if (p8 == NULL) return NULL; bag = PKCS12_SAFEBAG_create0_pkcs8(p8); if (bag == NULL) X509_SIG_free(p8); return bag; }
const EVP_CIPHER* get_cipher(lua_State*L, int idx, const char* def_alg) { const EVP_CIPHER* cipher = NULL; switch (lua_type(L, idx)) { case LUA_TSTRING: cipher = EVP_get_cipherbyname(lua_tostring(L, idx)); break; case LUA_TNUMBER: cipher = EVP_get_cipherbynid(lua_tointeger(L, idx)); break; case LUA_TUSERDATA: if (auxiliar_getclassudata(L, "openssl.asn1_object", idx)) cipher = EVP_get_cipherbyobj(CHECK_OBJECT(idx, ASN1_OBJECT, "openssl.asn1_object")); else if (auxiliar_getclassudata(L, "openssl.evp_cipher", idx)) cipher = CHECK_OBJECT(idx, EVP_CIPHER, "openssl.evp_cipher"); break; case LUA_TNONE: case LUA_TNIL: if (def_alg != NULL) cipher = EVP_get_cipherbyname(def_alg); break; } if (cipher==NULL) luaL_argerror(L, idx, "must be a string, NID number or asn1_object identity cipher method"); return cipher; }
void show_available_ciphers () { int nid; #ifndef ENABLE_SMALL printf ("The following ciphers and cipher modes are available\n" "for use with " PACKAGE_NAME ". Each cipher shown below may be\n" "used as a parameter to the --cipher option. The default\n" "key size is shown as well as whether or not it can be\n" "changed with the --keysize directive. Using a CBC mode\n" "is recommended.\n\n"); #endif for (nid = 0; nid < 10000; ++nid) /* is there a better way to get the size of the nid list? */ { const EVP_CIPHER *cipher = EVP_get_cipherbynid (nid); if (cipher) { const unsigned int mode = EVP_CIPHER_mode (cipher); if (mode == EVP_CIPH_CBC_MODE #ifdef ALLOW_NON_CBC_CIPHERS || mode == EVP_CIPH_CFB_MODE || mode == EVP_CIPH_OFB_MODE #endif ) printf ("%s %d bit default key (%s)\n", OBJ_nid2sn (nid), EVP_CIPHER_key_length (cipher) * 8, ((EVP_CIPHER_flags (cipher) & EVP_CIPH_VARIABLE_LENGTH) ? "variable" : "fixed")); } } printf ("\n"); }
void show_available_ciphers(void) { int nid; size_t i; /* If we ever exceed this, we must be more selective */ const EVP_CIPHER *cipher_list[1000]; size_t num_ciphers = 0; #ifndef ENABLE_SMALL printf("The following ciphers and cipher modes are available for use\n" "with " PACKAGE_NAME ". Each cipher shown below may be use as a\n" "parameter to the --cipher option. The default key size is\n" "shown as well as whether or not it can be changed with the\n" "--keysize directive. Using a CBC or GCM mode is recommended.\n" "In static key mode only CBC mode is allowed.\n\n"); #endif for (nid = 0; nid < 10000; ++nid) { const EVP_CIPHER *cipher = EVP_get_cipherbynid(nid); if (cipher && (cipher_kt_mode_cbc(cipher) #ifdef ENABLE_OFB_CFB_MODE || cipher_kt_mode_ofb_cfb(cipher) #endif #ifdef HAVE_AEAD_CIPHER_MODES || cipher_kt_mode_aead(cipher) #endif )) { cipher_list[num_ciphers++] = cipher; } if (num_ciphers == (sizeof(cipher_list)/sizeof(*cipher_list))) { msg(M_WARN, "WARNING: Too many ciphers, not showing all"); break; } } qsort(cipher_list, num_ciphers, sizeof(*cipher_list), cipher_name_cmp); for (i = 0; i < num_ciphers; i++) { if (!cipher_kt_insecure(cipher_list[i])) { print_cipher(cipher_list[i]); } } printf("\nThe following ciphers have a block size of less than 128 bits, \n" "and are therefore deprecated. Do not use unless you have to.\n\n"); for (i = 0; i < num_ciphers; i++) { if (cipher_kt_insecure(cipher_list[i])) { print_cipher(cipher_list[i]); } } printf("\n"); }
static int pbe_cipher_init(ASN1_OBJECT *pbe_obj, const uint8_t *pass_raw, size_t pass_raw_len, ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int is_encrypt) { const EVP_CIPHER *cipher; const EVP_MD *md; unsigned i; const struct pbe_suite *suite = NULL; const int pbe_nid = OBJ_obj2nid(pbe_obj); for (i = 0; i < sizeof(kBuiltinPBE) / sizeof(struct pbe_suite); i++) { suite = &kBuiltinPBE[i]; if (suite->pbe_nid == pbe_nid) { break; } } if (suite == NULL) { char obj_str[80]; OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_ALGORITHM); if (!pbe_obj) { strncpy(obj_str, "NULL", sizeof(obj_str)); } else { i2t_ASN1_OBJECT(obj_str, sizeof(obj_str), pbe_obj); } ERR_add_error_data(2, "TYPE=", obj_str); return 0; } if (suite->cipher_nid == -1) { cipher = NULL; } else { cipher = EVP_get_cipherbynid(suite->cipher_nid); if (!cipher) { OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_CIPHER); return 0; } } if (suite->md_nid == -1) { md = NULL; } else { md = EVP_get_digestbynid(suite->md_nid); if (!md) { OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_DIGEST); return 0; } } if (!suite->keygen(ctx, pass_raw, pass_raw_len, param, cipher, md, is_encrypt)) { OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_KEYGEN_FAILURE); return 0; } return 1; }
int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen, ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de) { const EVP_CIPHER *cipher; const EVP_MD *md; int cipher_nid, md_nid; EVP_PBE_KEYGEN *keygen; if (!EVP_PBE_find(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj), &cipher_nid, &md_nid, &keygen)) { char obj_tmp[80]; EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_PBE_ALGORITHM); if (!pbe_obj) BUF_strlcpy (obj_tmp, "NULL", sizeof obj_tmp); else i2t_ASN1_OBJECT(obj_tmp, sizeof obj_tmp, pbe_obj); ERR_add_error_data(2, "TYPE=", obj_tmp); return 0; } if(!pass) passlen = 0; else if (passlen == -1) passlen = strlen(pass); if (cipher_nid == -1) cipher = NULL; else { cipher = EVP_get_cipherbynid(cipher_nid); if (!cipher) { EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_CIPHER); return 0; } } if (md_nid == -1) md = NULL; else { md = EVP_get_digestbynid(md_nid); if (!md) { EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_DIGEST); return 0; } } if (!keygen(ctx, pass, passlen, param, cipher, md, en_de)) { EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_KEYGEN_FAILURE); return 0; } return 1; }
bool Crypto_t::symmetricCipher(const std::vector<unsigned char>& in_buffer, int nid, const std::string& key, const std::string& iv, bool encode, std::vector<unsigned char>& buffer) { // load all cipher modules OpenSSL_add_all_ciphers(); // Select the specific cipher module const EVP_CIPHER* cipher = EVP_get_cipherbynid(nid); if (!cipher) return false; // Each cipher has its own taste for the key and IV. So we need to check if the input key and IV is appropriate // for the specific cipher module if (key.size() < static_cast<size_t>(EVP_CIPHER_key_length(cipher)) || iv.size() < static_cast<size_t>(EVP_CIPHER_iv_length(cipher))) { return false; } EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); EVP_CipherInit_ex(&ctx, cipher, NULL, (const unsigned char*)key.c_str(), (const unsigned char*)iv.c_str(), encode); size_t block_size = EVP_CIPHER_block_size(cipher); unsigned char* encrypt_buffer = (unsigned char*) malloc(block_size + in_buffer.size()); // Read the raw buffer and convert to encrypt one. And then collect to the output buffer int out_count = 0; buffer.clear(); bool fail = false; while (true) { if (!EVP_CipherUpdate(&ctx, encrypt_buffer, &out_count, &in_buffer[0], in_buffer.size())) { fail = true; break; } for (int i = 0; i < out_count; i++) buffer.push_back(encrypt_buffer[i]); // handling the last block unsigned char* block = encrypt_buffer + out_count; if (!EVP_CipherFinal_ex(&ctx, block, &out_count)) { fail = true; break; } for (int i = 0; i < out_count; i++) buffer.push_back(block[i]); break; } // free resource free(encrypt_buffer); EVP_CIPHER_CTX_cleanup(&ctx); return (fail == true) ? (false) : (true); }
static void get_EVP_CIPHER_once_cb(void *d) { struct once_init_cipher_ctx *arg = d; const EVP_CIPHER *ossl_evp; hc_EVP_CIPHER *hc_evp; hc_evp = arg->hc_memoize; /* * We lookup EVP_CIPHER *s by NID so that we don't fail to find a * symbol such as EVP_aes...() when libcrypto changes after build * time (e.g., updates, LD_LIBRARY_PATH/LD_PRELOAD). */ ossl_evp = EVP_get_cipherbynid(arg->nid); if (ossl_evp == NULL) { (void) memset(hc_evp, 0, sizeof(*hc_evp)); #if HCRYPTO_FALLBACK *arg->hc_memoizep = arg->fallback; #endif return; } /* Build the hc_EVP_CIPHER */ hc_evp->nid = EVP_CIPHER_nid(ossl_evp); /* We would an hcrypto NIDs if we had them */ hc_evp->block_size = EVP_CIPHER_block_size(ossl_evp); hc_evp->key_len = EVP_CIPHER_key_length(ossl_evp); hc_evp->iv_len = EVP_CIPHER_iv_length(ossl_evp); /* * We force hc_EVP_CipherInit_ex to always call our init() function, * otherwise we don't get a chance to call EVP_CipherInit_ex() * correctly. */ hc_evp->flags = hc_EVP_CIPH_ALWAYS_CALL_INIT | arg->flags; /* Our cipher context */ hc_evp->ctx_size = sizeof(struct ossl_cipher_ctx); /* Our wrappers */ hc_evp->init = cipher_ctx_init; hc_evp->do_cipher = cipher_do_cipher; hc_evp->cleanup = cipher_cleanup; hc_evp->set_asn1_parameters = NULL; hc_evp->get_asn1_parameters = NULL; hc_evp->ctrl = cipher_ctrl; /* Our link to the OpenSSL EVP_CIPHER */ hc_evp->app_data = (void *)ossl_evp; /* Finally, set the static hc_EVP_CIPHER * to the one we just built */ *arg->hc_memoizep = hc_evp; }
CipherContext *crypto_decrypt_init(Encryption *params) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); if (!ctx) crypto_handle_error(); int nid = crypto_get_cipher_nid(params->algorithm, params->mode); const EVP_CIPHER *cipher = EVP_get_cipherbynid(nid); unsigned char key[64], iv[64]; crypto_get_key(cipher, params->password, key, iv); if (EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv) != 1) crypto_handle_error(); return ctx; }
/** Returns the OpenSSL keyblock size * * @copyright (c) 2002-2016, Jouni Malinen <*****@*****.**> and contributors * All Rights Reserved. * * These programs are licensed under the BSD license (the one with * advertisement clause removed). * * this function shamelessly stolen from from * hostap:src/crypto/tls_openssl.c:openssl_get_keyblock_size() * * @param[in] request The current request. * @param[in] ssl The current SSL session. * @return * - -1 problem with the session. * - >=0 length of the block. */ int tls_utils_keyblock_size_get(REQUEST *request, SSL *ssl) { const EVP_CIPHER *c; const EVP_MD *h; #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) int md_size; if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL || ssl->read_hash == NULL) return -1; c = ssl->enc_read_ctx->cipher; h = EVP_MD_CTX_md(ssl->read_hash); if (h) md_size = EVP_MD_size(h); else if (ssl->s3) md_size = ssl->s3->tmp.new_mac_secret_size; else return -1; RDEBUG2("OpenSSL: keyblock size: key_len=%d MD_size=%d " "IV_len=%d", EVP_CIPHER_key_length(c), md_size, EVP_CIPHER_iv_length(c)); return 2 * (EVP_CIPHER_key_length(c) + md_size + EVP_CIPHER_iv_length(c)); #else const SSL_CIPHER *ssl_cipher; int cipher, digest; ssl_cipher = SSL_get_current_cipher(ssl); if (!ssl_cipher) return -1; cipher = SSL_CIPHER_get_cipher_nid(ssl_cipher); digest = SSL_CIPHER_get_digest_nid(ssl_cipher); RDEBUG2("OpenSSL: cipher nid %d digest nid %d", cipher, digest); if (cipher < 0 || digest < 0) return -1; c = EVP_get_cipherbynid(cipher); h = EVP_get_digestbynid(digest); if (!c || !h) return -1; RDEBUG2("OpenSSL: keyblock size: key_len=%d MD_size=%d IV_len=%d", EVP_CIPHER_key_length(c), EVP_MD_size(h), EVP_CIPHER_iv_length(c)); return 2 * (EVP_CIPHER_key_length(c) + EVP_MD_size(h) + EVP_CIPHER_iv_length(c)); #endif }
void show_available_ciphers () { int nid; #ifndef ENABLE_SMALL printf ("The following ciphers and cipher modes are available for use\n" "with " PACKAGE_NAME ". Each cipher shown below may be use as a\n" "parameter to the --cipher option. The default key size is\n" "shown as well as whether or not it can be changed with the\n" "--keysize directive. Using a CBC or GCM mode is recommended.\n" "In static key mode only CBC mode is allowed.\n\n"); #endif for (nid = 0; nid < 10000; ++nid) /* is there a better way to get the size of the nid list? */ { const EVP_CIPHER *cipher = EVP_get_cipherbynid (nid); if (cipher) { if (cipher_kt_mode_cbc(cipher) #ifdef ENABLE_OFB_CFB_MODE || cipher_kt_mode_ofb_cfb(cipher) #endif #ifdef HAVE_AEAD_CIPHER_MODES || cipher_kt_mode_aead(cipher) #endif ) { const char *var_key_size = (EVP_CIPHER_flags (cipher) & EVP_CIPH_VARIABLE_LENGTH) ? "variable" : "fixed"; const char *ssl_only = cipher_kt_mode_cbc(cipher) ? "" : " (TLS client/server mode)"; printf ("%s %d bit default key (%s)%s\n", translate_cipher_name_to_openvpn(OBJ_nid2sn (nid)), EVP_CIPHER_key_length (cipher) * 8, var_key_size, ssl_only); } } } printf ("\n"); }
const EVP_CIPHER* get_cipher(lua_State*L, int idx, const char* def_alg) { const EVP_CIPHER* cipher = NULL; if (lua_isstring(L, idx)) cipher = EVP_get_cipherbyname(lua_tostring(L, idx)); else if (lua_isnumber(L, idx)) cipher = EVP_get_cipherbynid(lua_tointeger(L, idx)); else if (auxiliar_isclass(L, "openssl.asn1_object", idx)) cipher = EVP_get_cipherbyobj(CHECK_OBJECT(1, ASN1_OBJECT, "openssl.asn1_object")); else if (auxiliar_isclass(L, "openssl.evp_cipher", idx)) cipher = CHECK_OBJECT(idx, EVP_CIPHER, "openssl.evp_cipher"); else if (lua_isnoneornil(L, idx) && def_alg) cipher = EVP_get_cipherbyname(def_alg); else luaL_argerror(L, idx, "must be a string, NID number or asn1_object identity cipher method"); if (cipher == NULL) luaL_argerror(L, idx, "not valid cipher alg"); return cipher; }
/* This equivalent functionality was submitted for OpenSSL 1.1.1+ in * https://github.com/openssl/openssl/pull/1666 */ static int dtls_get_data_mtu(struct openconnect_info *vpninfo, int mtu) { int ivlen, maclen, blocksize = 0, pad = 0; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) const SSL_CIPHER *s_ciph = SSL_get_current_cipher(vpninfo->dtls_ssl); int cipher_nid; const EVP_CIPHER *e_ciph; const EVP_MD *e_md; char wtf[128]; cipher_nid = SSL_CIPHER_get_cipher_nid(s_ciph); if (cipher_nid == NID_chacha20_poly1305) { ivlen = 0; /* Automatically derived from handshake and seqno */ maclen = 16; /* Poly1305 */ } else { e_ciph = EVP_get_cipherbynid(cipher_nid); switch (EVP_CIPHER_mode(e_ciph)) { case EVP_CIPH_GCM_MODE: ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN; maclen = EVP_GCM_TLS_TAG_LEN; break; case EVP_CIPH_CCM_MODE: ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN; SSL_CIPHER_description(s_ciph, wtf, sizeof(wtf)); if (strstr(wtf, "CCM8")) maclen = 8; else maclen = 16; break; case EVP_CIPH_CBC_MODE: blocksize = EVP_CIPHER_block_size(e_ciph); ivlen = EVP_CIPHER_iv_length(e_ciph); pad = 1; e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph)); maclen = EVP_MD_size(e_md); break; default: vpn_progress(vpninfo, PRG_ERR, _("Unable to calculate DTLS overhead for %s\n"), SSL_CIPHER_get_name(s_ciph)); ivlen = 0; maclen = DTLS_OVERHEAD; break; } } #else /* OpenSSL <= 1.0.2 only supports CBC ciphers with PSK */ ivlen = EVP_CIPHER_iv_length(EVP_CIPHER_CTX_cipher(vpninfo->dtls_ssl->enc_read_ctx)); maclen = EVP_MD_CTX_size(vpninfo->dtls_ssl->read_hash); blocksize = ivlen; pad = 1; #endif /* Even when it pretended to, OpenSSL never did encrypt-then-mac. * So the MAC is *inside* the encryption, unconditionally. * https://github.com/openssl/openssl/pull/1705 */ if (mtu < DTLS1_RT_HEADER_LENGTH + ivlen) return 0; mtu -= DTLS1_RT_HEADER_LENGTH + ivlen; /* For CBC mode round down to blocksize */ if (blocksize) mtu -= mtu % blocksize; /* Finally, CBC modes require at least one byte to indicate * padding length, as well as the MAC. */ if (mtu < pad + maclen) return 0; mtu -= pad + maclen; return mtu; }
bool ans_key_h(connection_t *c) { char from_name[MAX_STRING_SIZE]; char to_name[MAX_STRING_SIZE]; char key[MAX_STRING_SIZE]; char address[MAX_STRING_SIZE] = ""; char port[MAX_STRING_SIZE] = ""; int cipher, digest, maclength, compression; node_t *from, *to; if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d "MAX_STRING" "MAX_STRING, from_name, to_name, key, &cipher, &digest, &maclength, &compression, address, port) < 7) { logger(LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name, c->hostname); return false; } if(!check_id(from_name) || !check_id(to_name)) { logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name"); return false; } from = lookup_node(from_name); if(!from) { logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list", "ANS_KEY", c->name, c->hostname, from_name); return true; } to = lookup_node(to_name); if(!to) { logger(LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list", "ANS_KEY", c->name, c->hostname, to_name); return true; } /* Forward it if necessary */ if(to != myself) { if(tunnelserver) return true; if(!to->status.reachable) { logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable", "ANS_KEY", c->name, c->hostname, to_name); return true; } if(!*address && from->address.sa.sa_family != AF_UNSPEC) { char *address, *port; ifdebug(PROTOCOL) logger(LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name); sockaddr2str(&from->address, &address, &port); send_request(to->nexthop->connection, "%s %s %s", c->buffer, address, port); free(address); free(port); return true; } return send_request(to->nexthop->connection, "%s", c->buffer); } /* Update our copy of the origin's packet key */ from->outkey = xrealloc(from->outkey, strlen(key) / 2); from->outkeylength = strlen(key) / 2; hex2bin(key, from->outkey, from->outkeylength); /* Check and lookup cipher and digest algorithms */ if(cipher) { from->outcipher = EVP_get_cipherbynid(cipher); if(!from->outcipher) { logger(LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname); return true; } if(from->outkeylength != from->outcipher->key_len + from->outcipher->iv_len) { logger(LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname); return true; } } else { from->outcipher = NULL; } from->outmaclength = maclength; if(digest) { from->outdigest = EVP_get_digestbynid(digest); if(!from->outdigest) { logger(LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname); return true; } if(from->outmaclength > from->outdigest->md_size || from->outmaclength < 0) { logger(LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname); return true; } } else { from->outdigest = NULL; } if(compression < 0 || compression > 11) { logger(LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname); return true; } from->outcompression = compression; if(from->outcipher) if(!EVP_EncryptInit_ex(&from->outctx, from->outcipher, NULL, (unsigned char *)from->outkey, (unsigned char *)from->outkey + from->outcipher->key_len)) { logger(LOG_ERR, "Error during initialisation of key from %s (%s): %s", from->name, from->hostname, ERR_error_string(ERR_get_error(), NULL)); return true; } from->status.validkey = true; from->sent_seqno = 0; if(*address && *port) { ifdebug(PROTOCOL) logger(LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port); sockaddr_t sa = str2sockaddr(address, port); update_node_udp(from, &sa); } if(from->options & OPTION_PMTU_DISCOVERY && !from->mtuevent) send_mtu_probe(from); return true; }
int OTP_generate(const OTP_PARAMS *params, const void *event, size_t eventlen, unsigned int *otp, const unsigned char *key, size_t keylen) { int ret = 0; time_t t = 0; unsigned char *id = NULL; size_t idlen; const EVP_MD *md; const EVP_CIPHER *cipher; EVP_MD_CTX *mdctx = NULL; CMAC_CTX *cmctx = NULL; unsigned char s[EVP_MAX_MD_SIZE]; size_t slen; uint32_t od; int i, n; OPENSSL_assert(sizeof(time_t) == 8); if (!check_params(params)) { OTPerr(OTP_F_OTP_GENERATE, OTP_R_INVALID_PARAMS); return 0; } idlen = sizeof(uint64_t) + eventlen + params->option_size; if (idlen < 16) { idlen = 16; } if (!(id = OPENSSL_malloc(idlen))) { OTPerr(OTP_F_OTP_GENERATE, ERR_R_MALLOC_FAILURE); goto end; } memset(id, 0, idlen); t = time(NULL) + params->offset; t /= params->te; memcpy(id, &t, sizeof(t)); memcpy(id + sizeof(t), event, eventlen); memcpy(id + sizeof(t) + eventlen, params->option, params->option_size); /* FIXME: try to get md and cipher, and check if cipher is ECB */ if (params->type == NID_sm3) { md = EVP_get_digestbynid(params->type); if (!(mdctx = EVP_MD_CTX_new())) { OTPerr(OTP_F_OTP_GENERATE, ERR_R_MALLOC_FAILURE); goto end; } if (!EVP_DigestInit_ex(mdctx, md, NULL)) { OTPerr(OTP_F_OTP_GENERATE, ERR_R_EVP_LIB); goto end; } if (!EVP_DigestUpdate(mdctx, key, keylen)) { OTPerr(OTP_F_OTP_GENERATE, ERR_R_EVP_LIB); goto end; } if (!EVP_DigestUpdate(mdctx, id, idlen)) { OTPerr(OTP_F_OTP_GENERATE, ERR_R_EVP_LIB); goto end; } if (!EVP_DigestFinal_ex(mdctx, s, (unsigned int *)&slen)) { OTPerr(OTP_F_OTP_GENERATE, ERR_R_EVP_LIB); goto end; } } else if (params->type == NID_sms4_ecb) { cipher = EVP_get_cipherbynid(params->type); if (!(cmctx = CMAC_CTX_new())) { OTPerr(OTP_F_OTP_GENERATE, ERR_R_MALLOC_FAILURE); goto end; } if (!CMAC_Init(cmctx, key, keylen, cipher, NULL)) { OTPerr(OTP_F_OTP_GENERATE, OTP_R_CMAC_FAILURE); goto end; } if (!CMAC_Update(cmctx, id, idlen)) { OTPerr(OTP_F_OTP_GENERATE, OTP_R_CMAC_FAILURE); goto end; } if (!CMAC_Final(cmctx, s, &slen)) { OTPerr(OTP_F_OTP_GENERATE, OTP_R_CMAC_FAILURE); goto end; } } else { goto end; } OPENSSL_assert(slen % 4 == 0); od = 0; n = (int)slen; for (i = 0; i < n/4; i++) { od += GETU32(&s[i * 4]); } *otp = od % pow_table[params->otp_digits]; ret = 1; end: OPENSSL_free(id); EVP_MD_CTX_free(mdctx); CMAC_CTX_free(cmctx); return ret; }
int tls13_change_cipher_state(SSL *s, int which) { static const unsigned char client_early_traffic[] = "c e traffic"; static const unsigned char client_handshake_traffic[] = "c hs traffic"; static const unsigned char client_application_traffic[] = "c ap traffic"; static const unsigned char server_handshake_traffic[] = "s hs traffic"; static const unsigned char server_application_traffic[] = "s ap traffic"; static const unsigned char exporter_master_secret[] = "exp master"; static const unsigned char resumption_master_secret[] = "res master"; static const unsigned char early_exporter_master_secret[] = "e exp master"; unsigned char *iv; unsigned char secret[EVP_MAX_MD_SIZE]; unsigned char hashval[EVP_MAX_MD_SIZE]; unsigned char *hash = hashval; unsigned char *insecret; unsigned char *finsecret = NULL; const char *log_label = NULL; EVP_CIPHER_CTX *ciph_ctx; size_t finsecretlen = 0; const unsigned char *label; size_t labellen, hashlen = 0; int ret = 0; const EVP_MD *md = NULL; const EVP_CIPHER *cipher = NULL; if (which & SSL3_CC_READ) { if (s->enc_read_ctx != NULL) { EVP_CIPHER_CTX_reset(s->enc_read_ctx); } else { s->enc_read_ctx = EVP_CIPHER_CTX_new(); if (s->enc_read_ctx == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); goto err; } } ciph_ctx = s->enc_read_ctx; iv = s->read_iv; RECORD_LAYER_reset_read_sequence(&s->rlayer); } else { s->statem.enc_write_state = ENC_WRITE_STATE_INVALID; if (s->enc_write_ctx != NULL) { EVP_CIPHER_CTX_reset(s->enc_write_ctx); } else { s->enc_write_ctx = EVP_CIPHER_CTX_new(); if (s->enc_write_ctx == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); goto err; } } ciph_ctx = s->enc_write_ctx; iv = s->write_iv; RECORD_LAYER_reset_write_sequence(&s->rlayer); } if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE)) || ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) { if (which & SSL3_CC_EARLY) { EVP_MD_CTX *mdctx = NULL; long handlen; void *hdata; unsigned int hashlenui; const SSL_CIPHER *sslcipher = SSL_SESSION_get0_cipher(s->session); insecret = s->early_secret; label = client_early_traffic; labellen = sizeof(client_early_traffic) - 1; log_label = CLIENT_EARLY_LABEL; handlen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); if (handlen <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, SSL_R_BAD_HANDSHAKE_LENGTH); goto err; } if (s->early_data_state == SSL_EARLY_DATA_CONNECTING && s->max_early_data > 0 && s->session->ext.max_early_data == 0) { /* * If we are attempting to send early data, and we've decided to * actually do it but max_early_data in s->session is 0 then we * must be using an external PSK. */ if (!ossl_assert(s->psksession != NULL && s->max_early_data == s->psksession->ext.max_early_data)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); goto err; } sslcipher = SSL_SESSION_get0_cipher(s->psksession); } if (sslcipher == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, SSL_R_BAD_PSK); goto err; } /* * We need to calculate the handshake digest using the digest from * the session. We haven't yet selected our ciphersuite so we can't * use ssl_handshake_md(). */ mdctx = EVP_MD_CTX_new(); if (mdctx == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); goto err; } cipher = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(sslcipher)); md = ssl_md(sslcipher->algorithm2); if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL) || !EVP_DigestUpdate(mdctx, hdata, handlen) || !EVP_DigestFinal_ex(mdctx, hashval, &hashlenui)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); EVP_MD_CTX_free(mdctx); goto err; } hashlen = hashlenui; EVP_MD_CTX_free(mdctx); if (!tls13_hkdf_expand(s, md, insecret, early_exporter_master_secret, sizeof(early_exporter_master_secret) - 1, hashval, hashlen, s->early_exporter_master_secret, hashlen, 1)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); goto err; } if (!ssl_log_secret(s, EARLY_EXPORTER_SECRET_LABEL, s->early_exporter_master_secret, hashlen)) { /* SSLfatal() already called */ goto err; } } else if (which & SSL3_CC_HANDSHAKE) { insecret = s->handshake_secret; finsecret = s->client_finished_secret; finsecretlen = EVP_MD_size(ssl_handshake_md(s)); label = client_handshake_traffic; labellen = sizeof(client_handshake_traffic) - 1; log_label = CLIENT_HANDSHAKE_LABEL; /* * The handshake hash used for the server read/client write handshake * traffic secret is the same as the hash for the server * write/client read handshake traffic secret. However, if we * processed early data then we delay changing the server * read/client write cipher state until later, and the handshake * hashes have moved on. Therefore we use the value saved earlier * when we did the server write/client read change cipher state. */ hash = s->handshake_traffic_hash; } else { insecret = s->master_secret; label = client_application_traffic; labellen = sizeof(client_application_traffic) - 1; log_label = CLIENT_APPLICATION_LABEL; /* * For this we only use the handshake hashes up until the server * Finished hash. We do not include the client's Finished, which is * what ssl_handshake_hash() would give us. Instead we use the * previously saved value. */ hash = s->server_finished_hash; } } else { /* Early data never applies to client-read/server-write */ if (which & SSL3_CC_HANDSHAKE) { insecret = s->handshake_secret; finsecret = s->server_finished_secret; finsecretlen = EVP_MD_size(ssl_handshake_md(s)); label = server_handshake_traffic; labellen = sizeof(server_handshake_traffic) - 1; log_label = SERVER_HANDSHAKE_LABEL; } else { insecret = s->master_secret; label = server_application_traffic; labellen = sizeof(server_application_traffic) - 1; log_label = SERVER_APPLICATION_LABEL; } } if (!(which & SSL3_CC_EARLY)) { md = ssl_handshake_md(s); cipher = s->s3->tmp.new_sym_enc; if (!ssl3_digest_cached_records(s, 1) || !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) { /* SSLfatal() already called */; goto err; } } /* * Save the hash of handshakes up to now for use when we calculate the * client application traffic secret */ if (label == server_application_traffic) memcpy(s->server_finished_hash, hashval, hashlen); if (label == server_handshake_traffic) memcpy(s->handshake_traffic_hash, hashval, hashlen); if (label == client_application_traffic) { /* * We also create the resumption master secret, but this time use the * hash for the whole handshake including the Client Finished */ if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret, resumption_master_secret, sizeof(resumption_master_secret) - 1, hashval, hashlen, s->resumption_master_secret, hashlen, 1)) { /* SSLfatal() already called */ goto err; } } if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher, insecret, hash, label, labellen, secret, iv, ciph_ctx)) { /* SSLfatal() already called */ goto err; } if (label == server_application_traffic) { memcpy(s->server_app_traffic_secret, secret, hashlen); /* Now we create the exporter master secret */ if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret, exporter_master_secret, sizeof(exporter_master_secret) - 1, hash, hashlen, s->exporter_master_secret, hashlen, 1)) { /* SSLfatal() already called */ goto err; } if (!ssl_log_secret(s, EXPORTER_SECRET_LABEL, s->exporter_master_secret, hashlen)) { /* SSLfatal() already called */ goto err; } } else if (label == client_application_traffic) memcpy(s->client_app_traffic_secret, secret, hashlen); if (!ssl_log_secret(s, log_label, secret, hashlen)) { /* SSLfatal() already called */ goto err; } if (finsecret != NULL && !tls13_derive_finishedkey(s, ssl_handshake_md(s), secret, finsecret, finsecretlen)) { /* SSLfatal() already called */ goto err; } if (!s->server && label == client_early_traffic) s->statem.enc_write_state = ENC_WRITE_STATE_WRITE_PLAIN_ALERTS; else s->statem.enc_write_state = ENC_WRITE_STATE_VALID; ret = 1; err: OPENSSL_cleanse(secret, sizeof(secret)); return ret; }
bool metakey_h(connection_t *c) { char buffer[MAX_STRING_SIZE]; int cipher, digest, maclength, compression; int len; if(sscanf(c->buffer, "%*d %d %d %d %d " MAX_STRING, &cipher, &digest, &maclength, &compression, buffer) != 5) { logger(LOG_ERR, "Got bad %s from %s (%s)", "METAKEY", c->name, c->hostname); return false; } len = RSA_size(myself->connection->rsa_key); /* Check if the length of the meta key is all right */ if(strlen(buffer) != (size_t)len * 2) { logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong keylength"); return false; } /* Allocate buffers for the meta key */ c->inkey = xrealloc(c->inkey, len); if(!c->inctx) { c->inctx = EVP_CIPHER_CTX_new(); if(!c->inctx) { abort(); } } /* Convert the challenge from hexadecimal back to binary */ if(!hex2bin(buffer, buffer, len)) { logger(LOG_ERR, "Got bad %s from %s(%s): %s", "METAKEY", c->name, c->hostname, "invalid key"); return false; } /* Decrypt the meta key */ if(RSA_private_decrypt(len, (unsigned char *)buffer, (unsigned char *)c->inkey, myself->connection->rsa_key, RSA_NO_PADDING) != len) { /* See challenge() */ logger(LOG_ERR, "Error during decryption of meta key for %s (%s): %s", c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); return false; } ifdebug(SCARY_THINGS) { bin2hex(c->inkey, buffer, len); buffer[len * 2] = '\0'; logger(LOG_DEBUG, "Received random meta key (unencrypted): %s", buffer); } /* All incoming requests will now be encrypted. */ /* Check and lookup cipher and digest algorithms */ if(cipher) { c->incipher = EVP_get_cipherbynid(cipher); if(!c->incipher) { logger(LOG_ERR, "%s (%s) uses unknown cipher!", c->name, c->hostname); return false; } if(!EVP_DecryptInit(c->inctx, c->incipher, (unsigned char *)c->inkey + len - EVP_CIPHER_key_length(c->incipher), (unsigned char *)c->inkey + len - EVP_CIPHER_key_length(c->incipher) - EVP_CIPHER_iv_length(c->incipher))) { logger(LOG_ERR, "Error during initialisation of cipher from %s (%s): %s", c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); return false; } c->inbudget = byte_budget(c->incipher); c->status.decryptin = true; } else { logger(LOG_ERR, "%s (%s) uses null cipher!", c->name, c->hostname); return false; } c->inmaclength = maclength; if(digest) { c->indigest = EVP_get_digestbynid(digest); if(!c->indigest) { logger(LOG_ERR, "Node %s (%s) uses unknown digest!", c->name, c->hostname); return false; } if(c->inmaclength > EVP_MD_size(c->indigest) || c->inmaclength < 0) { logger(LOG_ERR, "%s (%s) uses bogus MAC length!", c->name, c->hostname); return false; } } else { logger(LOG_ERR, "%s (%s) uses null digest!", c->name, c->hostname); return false; } c->incompression = compression; c->allow_request = CHALLENGE; return send_challenge(c); }