bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed) { EC_KEY_free(pkey); pkey = EC_KEY_new_by_curve_name(NID_secp256k1); if (pkey == NULL) throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed"); if (vchSecret.size() != 32) throw key_error("CKey::SetSecret() : secret must be 32 bytes"); BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new()); if (bn == NULL) throw key_error("CKey::SetSecret() : BN_bin2bn failed"); if (!EC_KEY_regenerate_key(pkey,bn)) { BN_clear_free(bn); throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed"); } BN_clear_free(bn); fSet = true; if (fCompressed || fCompressedPubKey) SetCompressedPubKey(); return true; }
/* ECDH temporary parameters */ static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value) { int rv = 1; EC_KEY *ecdh; int nid; nid = EC_curve_nist2nid(value); if (nid == NID_undef) nid = OBJ_sn2nid(value); if (nid == 0) return 0; ecdh = EC_KEY_new_by_curve_name(nid); if (!ecdh) return 0; if (cctx->ctx) rv = SSL_CTX_set_tmp_ecdh(cctx->ctx, ecdh); else if (cctx->ssl) rv = SSL_set_tmp_ecdh(cctx->ssl, ecdh); EC_KEY_free(ecdh); return rv > 0; }
static void initialize_ecdh(void) { #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_ECDH) EC_KEY *ecdh; int nid; nid = OBJ_sn2nid(SSLECDHCurve); if (!nid) ereport(FATAL, (errmsg("ECDH: unrecognized curve name: %s", SSLECDHCurve))); ecdh = EC_KEY_new_by_curve_name(nid); if (!ecdh) ereport(FATAL, (errmsg("ECDH: could not create key"))); SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_ECDH_USE); SSL_CTX_set_tmp_ecdh(SSL_context, ecdh); EC_KEY_free(ecdh); #endif }
SOTER_PRIVATE_API soter_status_t soter_asym_ka_init(soter_asym_ka_t* asym_ka_ctx, soter_asym_ka_alg_t alg) { EVP_PKEY* pkey; int nid = soter_alg_to_curve_nid(alg); if ((!asym_ka_ctx) || (0 == nid)) { return SOTER_INVALID_PARAMETER; } pkey = EVP_PKEY_new(); if (!pkey) { return SOTER_NO_MEMORY; } if (!EVP_PKEY_set_type(pkey, EVP_PKEY_EC)) { EVP_PKEY_free(pkey); return SOTER_FAIL; } asym_ka_ctx->pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!(asym_ka_ctx->pkey_ctx)) { EVP_PKEY_free(pkey); return SOTER_FAIL; } EC_KEY* ec = EC_KEY_new_by_curve_name(nid); if (!ec) { EVP_PKEY_CTX_free(asym_ka_ctx->pkey_ctx); return SOTER_FAIL; } if (1 != EVP_PKEY_set1_EC_KEY(pkey, ec)) { EVP_PKEY_CTX_free(asym_ka_ctx->pkey_ctx); EC_KEY_free(ec); return SOTER_FAIL; } EC_KEY_free(ec); return SOTER_SUCCESS; }
static isc_result_t opensslecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { isc_result_t ret; EVP_PKEY *pkey; EC_KEY *eckey = NULL; int group_nid; REQUIRE(key->key_alg == DST_ALG_ECDSA256 || key->key_alg == DST_ALG_ECDSA384); UNUSED(unused); UNUSED(callback); if (key->key_alg == DST_ALG_ECDSA256) group_nid = NID_X9_62_prime256v1; else group_nid = NID_secp384r1; eckey = EC_KEY_new_by_curve_name(group_nid); if (eckey == NULL) return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); if (EC_KEY_generate_key(eckey) != 1) DST_RET (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); pkey = EVP_PKEY_new(); if (pkey == NULL) DST_RET (ISC_R_NOMEMORY); if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { EVP_PKEY_free(pkey); DST_RET (ISC_R_FAILURE); } key->keydata.pkey = pkey; ret = ISC_R_SUCCESS; err: if (eckey != NULL) EC_KEY_free(eckey); return (ret); }
void SSLCommon::load_ecdh_params(SSL_CTX *ctx, Logger &logger) { SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_SSLv2); /* Cheesily pick an elliptic curve to use with elliptic curve ciphersuites. * We just hardcode a single curve which is reasonably decent. * See http://www.mail-archive.com/[email protected]/msg30957.html */ EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1); if (! ecdh) { logger << "Couldn't create elliptic curve" << endl; exitSSL("EC_KEY_new_by_curve_name(ecdh)"); } if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) { logger << "Couldn't set ecdh parameters" << endl; exitSSL("SSL_CTX_set_tmp_ecdh(ecdh)"); } }
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) { EC_POINT *p; const EC_GROUP *g; int ok; key->ecdsa_nid = nid; key->type_c = pki_key_ecdsa_nid_to_name(nid); key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); if (key->ecdsa == NULL) { return -1; } g = EC_KEY_get0_group(key->ecdsa); p = EC_POINT_new(g); if (p == NULL) { return -1; } ok = EC_POINT_oct2point(g, p, ssh_string_data(e), ssh_string_len(e), NULL); if (!ok) { EC_POINT_free(p); return -1; } ok = EC_KEY_set_public_key(key->ecdsa, p); if (!ok) { EC_POINT_free(p); } return 0; }
// reconstruct public key from a compact signature // This is only slightly more CPU intensive than just verifying it. // If this function succeeds, the recovered public key is guaranteed to be valid // (the signature is a valid signature of the given data for that key) bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig) { if (vchSig.size() != 65) return false; int nV = vchSig[0]; if (nV<27 || nV>=35) return false; ECDSA_SIG *sig = ECDSA_SIG_new(); if (!sig) return false; #if OPENSSL_VERSION_NUMBER > 0x1000ffffL // sig_r and sig_s are deallocated by ECDSA_SIG_free(sig); BIGNUM *sig_r = BN_bin2bn(&vchSig[1],32,BN_new()); BIGNUM *sig_s = BN_bin2bn(&vchSig[33],32,BN_new()); if (!sig_r || !sig_s) return false; // copy and transfer ownership to sig ECDSA_SIG_set0(sig, sig_r, sig_s); #else BN_bin2bn(&vchSig[1],32,sig->r); BN_bin2bn(&vchSig[33],32,sig->s); #endif EC_KEY_free(pkey); pkey = EC_KEY_new_by_curve_name(NID_secp256k1); if (nV >= 31) { SetCompressedPubKey(); nV -= 4; } if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1) { fSet = true; ECDSA_SIG_free(sig); return true; } ECDSA_SIG_free(sig); return false; }
static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) { const uint8_t *p = NULL; void *pval; int ptype, pklen; EC_KEY *eckey = NULL; X509_ALGOR *palg; if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) { return 0; } X509_ALGOR_get0(NULL, &ptype, &pval, palg); if (ptype != V_ASN1_OBJECT) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return 0; } eckey = EC_KEY_new_by_curve_name(OBJ_obj2nid((ASN1_OBJECT *)pval)); if (eckey == NULL) { OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB); return 0; } /* We have parameters now set public key */ if (!o2i_ECPublicKey(&eckey, &p, pklen)) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); goto err; } EVP_PKEY_assign_EC_KEY(pkey, eckey); return 1; err: if (eckey) { EC_KEY_free(eckey); } return 0; }
static void attempt_parse_blob(u_char *blob, size_t len) { struct sshbuf *p1; BIGNUM *bn; EC_KEY *eck; u_char *s; size_t l; u_int8_t u8; u_int16_t u16; u_int32_t u32; u_int64_t u64; p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put(p1, blob, len), 0); sshbuf_get_u8(p1, &u8); sshbuf_get_u16(p1, &u16); sshbuf_get_u32(p1, &u32); sshbuf_get_u64(p1, &u64); if (sshbuf_get_string(p1, &s, &l) == 0) { bzero(s, l); free(s); } bn = BN_new(); if (sshbuf_get_bignum1(p1, bn) == 0) BN_clear_free(bn); bn = BN_new(); if (sshbuf_get_bignum2(p1, bn) == 0) BN_clear_free(bn); eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); ASSERT_PTR_NE(eck, NULL); if (sshbuf_get_eckey(p1, eck) == 0) EC_KEY_free(eck); sshbuf_free(p1); }
// Get the AlphaCrypt default PEER public Key EC_POINT * CAlphaCrypt::GetAlphaCryptPublicKey() { EC_KEY * lpPublicCurve = NULL; // Curve that contains the public key EC_POINT * pubKey = NULL; // Public key generated from the 2 coordinates const LPSTR XCoordHex = "46668077A4449322CA896BD64901DE333156B6FEAE75ABE5D4922A039B3CD013"; const LPSTR YCoordHex = "304AB8B3F15F498094F14058A1D1EBE823BEF512D44210CC50BBD94128D2CD05"; BIGNUM * pBnX = NULL, * pBnY = NULL; int iRet = 0; // Allocate the 2 points structures pBnX = BN_new(); pBnY = BN_new(); // Get X and Y Coordinate BN_hex2bn(&pBnX, XCoordHex); BN_hex2bn(&pBnY, YCoordHex); // Create the curve that contains the public key lpPublicCurve = EC_KEY_new_by_curve_name(NID_secp256k1); // Create the generator pubKey = EC_POINT_new(lpPublicCurve->group); // Generate the Public key and verify it EC_POINT_set_affine_coordinates_GFp(lpPublicCurve->group, pubKey, pBnX, pBnY, NULL); EC_KEY_set_public_key(lpPublicCurve, pubKey); iRet = EC_KEY_check_key(lpPublicCurve); // Cleanup EC_KEY_free(lpPublicCurve); BN_free(pBnX); BN_free(pBnY); if (iRet) return pubKey; else EC_POINT_free(pubKey); return NULL; }
static void test_ecdsa_sign(void) { EVP_PKEY *pkey; { /* create pkey */ EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); EC_KEY_generate_key(eckey); pkey = EVP_PKEY_new(); EVP_PKEY_set1_EC_KEY(pkey, eckey); EC_KEY_free(eckey); } const char *message = "hello world"; ptls_buffer_t sigbuf; uint8_t sigbuf_small[1024]; ptls_buffer_init(&sigbuf, sigbuf_small, sizeof(sigbuf_small)); ok(do_sign(pkey, &sigbuf, ptls_iovec_init(message, strlen(message)), EVP_sha256()) == 0); EVP_PKEY_up_ref(pkey); ok(verify_sign(pkey, ptls_iovec_init(message, strlen(message)), ptls_iovec_init(sigbuf.base, sigbuf.off)) == 0); ptls_buffer_dispose(&sigbuf); EVP_PKEY_free(pkey); }
void ssl_set_ecdh_curve(SSL_CTX *ctx, const char *curve) { int nid; EC_KEY *ecdh; if (curve == NULL) curve = SSL_ECDH_CURVE; if ((nid = OBJ_sn2nid(curve)) == 0) { ssl_error("ssl_set_ecdh_curve"); fatal("ssl_set_ecdh_curve: unknown curve name " SSL_ECDH_CURVE); } if ((ecdh = EC_KEY_new_by_curve_name(nid)) == NULL) { ssl_error("ssl_set_ecdh_curve"); fatal("ssl_set_ecdh_curve: unable to create curve " SSL_ECDH_CURVE); } SSL_CTX_set_tmp_ecdh(ctx, ecdh); SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); EC_KEY_free(ecdh); }
// reconstruct public key from a compact signature // This is only slightly more CPU intensive than just verifying it. // If this function succeeds, the recovered public key is guaranteed to be valid // (the signature is a valid signature of the given data for that key) bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char> &vchSig) { if (vchSig.size() != 65) return false; int nV = vchSig[0]; if (nV < 27 || nV >= 35) return false; ECDSA_SIG *sig = ECDSA_SIG_new(); BN_bin2bn(&vchSig[1], 32, sig->r); BN_bin2bn(&vchSig[33], 32, sig->s); EC_KEY_free(pkey); pkey = EC_KEY_new_by_curve_name(NID_secp256k1); if (nV >= 31) { SetCompressedPubKey(); nV -= 4; } if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char *)&hash, sizeof(hash), nV - 27, 0) == 1) { fSet = true; ECDSA_SIG_free(sig); return true; } return false; }
static int lws_context_ssl_init_ecdh_curve(struct lws_context_creation_info *info, struct lws_vhost *vhost) { #if defined(LWS_HAVE_OPENSSL_ECDH_H) && !defined(LWS_WITH_MBEDTLS) EC_KEY *ecdh; int ecdh_nid; const char *ecdh_curve = "prime256v1"; if (info->ecdh_curve) ecdh_curve = info->ecdh_curve; ecdh_nid = OBJ_sn2nid(ecdh_curve); if (NID_undef == ecdh_nid) { lwsl_err("SSL: Unknown curve name '%s'", ecdh_curve); return 1; } ecdh = EC_KEY_new_by_curve_name(ecdh_nid); if (NULL == ecdh) { lwsl_err("SSL: Unable to create curve '%s'", ecdh_curve); return 1; } SSL_CTX_set_tmp_ecdh(vhost->ssl_ctx, ecdh); EC_KEY_free(ecdh); SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_SINGLE_ECDH_USE); lwsl_notice(" SSL ECDH curve '%s'\n", ecdh_curve); #else #if !defined(LWS_WITH_MBEDTLS) lwsl_notice(" OpenSSL doesn't support ECDH\n"); #endif #endif return 0; }
static EP_STAT generate_ec_key(EP_CRYPTO_KEY *key, const char *curve) { if (curve == NULL) curve = ep_adm_getstrparam("libep.crypto.key.ec.curve", "sect283r1"); int nid = OBJ_txt2nid(curve); if (nid == NID_undef) { _ep_crypto_error("unknown EC curve name %s", curve); goto fail0; } EC_KEY *eckey = EC_KEY_new_by_curve_name(nid); if (eckey == NULL) { _ep_crypto_error("cannot create EC key"); goto fail0; } if (!EC_KEY_generate_key(eckey)) { _ep_crypto_error("cannot generate EC key"); goto fail1; } if (EVP_PKEY_assign_EC_KEY(key, eckey) != 1) { _ep_crypto_error("cannot assign EC key"); goto fail1; } return EP_STAT_OK; fail1: EC_KEY_free(eckey); fail0: return EP_STAT_CRYPTO_KEYCREATE; }
/* * Set elliptic curve. */ static int set_ec_params(SSL_CTX * ctx, const char* curve_name) { int curve = 0; if (curve_name) { curve = OBJ_txt2nid(curve_name); } if (curve > 0) { EC_KEY *ecdh = EC_KEY_new_by_curve_name (curve); if (! ecdh) { LM_ERR("unable to create EC curve\n"); return -1; } if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) { LM_ERR("unable to set tmp_ecdh\n"); return -1; } EC_KEY_free (ecdh); } else { LM_ERR("unable to find the EC curve\n"); return -1; } return 0; }
NOEXPORT int ecdh_init(SERVICE_OPTIONS *section) { #ifdef WITH_WOLFSSL /* wolfSSL automatically detects ecdh parameters from ECC key file. * No need to load explicitly */ (void)section; return 0; #else EC_KEY *ecdh; s_log(LOG_DEBUG, "ECDH initialization"); ecdh=EC_KEY_new_by_curve_name(section->curve); if(!ecdh) { sslerror("EC_KEY_new_by_curve_name"); s_log(LOG_ERR, "Cannot create curve %s", OBJ_nid2ln(section->curve)); return 1; /* FAILED */ } SSL_CTX_set_tmp_ecdh(section->ctx, ecdh); EC_KEY_free(ecdh); s_log(LOG_DEBUG, "ECDH initialized with curve %s", OBJ_nid2ln(section->curve)); return 0; /* OK */ #endif /* WITH_WOLFSSL */ }
int main (int argc, const char * argv[]) { EC_KEY *eckey; unsigned int curve; size_t digest_len; char name[1024], curve_name[200], pubkey[1024], privkey[1024]; if (!read_params(name, 1024, curve_name, 200, pubkey, 1024, privkey, 1024)) return ERR_STDIN_READ; ///*debug*/printf("%s\n%s\n%s\n%s\n", name, curve_name, pubkey, privkey); // Get curve type and digest_len if (strcmp(curve_name, "secp112r1") == 0) { curve = NID_secp112r1; digest_len = 14; } else if (strcmp(curve_name, "secp128r1") == 0) { curve = NID_secp128r1; digest_len = 16; } else if (strcmp(curve_name, "secp160r1") == 0) { curve = NID_secp160r1; digest_len = 20; } else { return ERR_CURVE_UNKNOWN; } eckey = EC_KEY_new_by_curve_name(curve); if (eckey == NULL) return ERR_INIT_KEY; // set public key unsigned char *bin = NULL; size_t len = hex2bin(&bin, pubkey); if (len == 0) return ERR_PUBLIC_KEY_DECODING; const unsigned char *bin_copy = bin; eckey = o2i_ECPublicKey(&eckey, &bin_copy, len); OPENSSL_free(bin); // set private key len = hex2bin(&bin, privkey); if (len == 0) return ERR_PUBLIC_KEY_DECODING; bin_copy = bin; eckey = d2i_ECPrivateKey(&eckey, &bin_copy, len); OPENSSL_free(bin); // check keys if (!EC_KEY_check_key(eckey)) return ERR_WRONG_KEYS; // calculate sha-1 unsigned char digest[digest_len]; el_compute_digest(name, digest, digest_len); // sign ECDSA_SIG *sig = ECDSA_do_sign(digest, digest_len, eckey); if (sig == NULL) return ERR_SIGNING; size_t rlen = BN_num_bytes(sig->r); size_t slen = BN_num_bytes(sig->s); size_t binlen = rlen + slen; bin = OPENSSL_malloc(binlen); bzero(bin, binlen); BN_bn2bin(sig->r, bin); BN_bn2bin(sig->s, bin + rlen); // join two values into bin ECDSA_SIG_free(sig); size_t b32len = el_base32_encode_buffer_size(binlen); char *base32 = OPENSSL_malloc(b32len); bzero(base32, b32len); el_base32_encode(bin, binlen, base32, b32len); printf("%s", base32); OPENSSL_free(bin); OPENSSL_free(base32); return 0; }
Key *key_private_deserialize(buffer_t *blob) { int success = 0; char *type_name = NULL; Key *k = NULL; unsigned int pklen, sklen; int type; type_name = buffer_get_string_msg(blob, NULL); if (type_name == NULL) goto error; type = get_keytype_from_name(type_name); k = key_new_private(type); switch (type) { case KEY_RSA: buffer_get_bignum2_msg(blob, k->rsa->n); buffer_get_bignum2_msg(blob, k->rsa->e); buffer_get_bignum2_msg(blob, k->rsa->d); buffer_get_bignum2_msg(blob, k->rsa->iqmp); buffer_get_bignum2_msg(blob, k->rsa->p); buffer_get_bignum2_msg(blob, k->rsa->q); /* Generate additional parameters */ rsa_generate_additional_parameters(k->rsa); break; case KEY_DSA: buffer_get_bignum2_msg(blob, k->dsa->p); buffer_get_bignum2_msg(blob, k->dsa->q); buffer_get_bignum2_msg(blob, k->dsa->g); buffer_get_bignum2_msg(blob, k->dsa->pub_key); buffer_get_bignum2_msg(blob, k->dsa->priv_key); break; case KEY_ECDSA256: case KEY_ECDSA384: case KEY_ECDSA521: { int success = 0; unsigned int nid; char *curve = NULL; ssh_keytype skt; BIGNUM *exponent = NULL; EC_POINT *q = NULL; nid = keytype_to_cipher_nid(type); curve = buffer_get_string_msg(blob, NULL); skt = key_curve_name_to_keytype(curve); if (nid != keytype_to_cipher_nid(skt)) goto ecdsa_error; k->ecdsa = EC_KEY_new_by_curve_name(nid); if (k->ecdsa == NULL) goto ecdsa_error; q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa)); if (q == NULL) goto ecdsa_error; if ((exponent = BN_new()) == NULL) goto ecdsa_error; buffer_get_ecpoint_msg(blob, EC_KEY_get0_group(k->ecdsa), q); buffer_get_bignum2_msg(blob, exponent); if (EC_KEY_set_public_key(k->ecdsa, q) != 1) goto ecdsa_error; if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) goto ecdsa_error; if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa), EC_KEY_get0_public_key(k->ecdsa)) != 0) goto ecdsa_error; if (key_ec_validate_private(k->ecdsa) != 0) goto ecdsa_error; success = 1; ecdsa_error: free(curve); if (exponent) BN_clear_free(exponent); if (q) EC_POINT_free(q); if (success == 0) goto error; } break; case KEY_ED25519: k->ed25519_pk = buffer_get_string_msg(blob, &pklen); k->ed25519_sk = buffer_get_string_msg(blob, &sklen); if (pklen != ED25519_PK_SZ) goto error; if (sklen != ED25519_SK_SZ) goto error; break; default: goto error; break; } /* enable blinding */ switch (k->type) { case KEY_RSA1: case KEY_RSA: if (RSA_blinding_on(k->rsa, NULL) != 1) goto error; break; } success = 1; error: free(type_name); if (success == 0) { key_free(k); k = NULL; } return (k); }
// // バッファからキー情報を取り出す(for SSH2) // NOTE: 返値はアロケート領域になるので、呼び出し側で解放すること。 // Key *key_from_blob(char *data, int blen) { int keynamelen, len; char key[128]; RSA *rsa = NULL; DSA *dsa = NULL; EC_KEY *ecdsa = NULL; EC_POINT *q = NULL; char *curve = NULL; Key *hostkey; // hostkey ssh_keytype type; unsigned char *pk = NULL; hostkey = malloc(sizeof(Key)); if (hostkey == NULL) goto error; memset(hostkey, 0, sizeof(Key)); keynamelen = get_uint32_MSBfirst(data); if (keynamelen >= sizeof(key)) { goto error; } data += 4; memcpy(key, data, keynamelen); key[keynamelen] = 0; data += keynamelen; type = get_keytype_from_name(key); switch (type) { case KEY_RSA: // RSA key rsa = RSA_new(); if (rsa == NULL) { goto error; } rsa->n = BN_new(); rsa->e = BN_new(); if (rsa->n == NULL || rsa->e == NULL) { goto error; } buffer_get_bignum2(&data, rsa->e); buffer_get_bignum2(&data, rsa->n); hostkey->type = type; hostkey->rsa = rsa; break; case KEY_DSA: // DSA key dsa = DSA_new(); if (dsa == NULL) { goto error; } dsa->p = BN_new(); dsa->q = BN_new(); dsa->g = BN_new(); dsa->pub_key = BN_new(); if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL || dsa->pub_key == NULL) { goto error; } buffer_get_bignum2(&data, dsa->p); buffer_get_bignum2(&data, dsa->q); buffer_get_bignum2(&data, dsa->g); buffer_get_bignum2(&data, dsa->pub_key); hostkey->type = type; hostkey->dsa = dsa; break; case KEY_ECDSA256: // ECDSA case KEY_ECDSA384: case KEY_ECDSA521: curve = buffer_get_string(&data, NULL); if (type != key_curve_name_to_keytype(curve)) { goto error; } ecdsa = EC_KEY_new_by_curve_name(keytype_to_cipher_nid(type)); if (ecdsa == NULL) { goto error; } q = EC_POINT_new(EC_KEY_get0_group(ecdsa)); if (q == NULL) { goto error; } buffer_get_ecpoint(&data, EC_KEY_get0_group(ecdsa), q); if (key_ec_validate_public(EC_KEY_get0_group(ecdsa), q) == -1) { goto error; } if (EC_KEY_set_public_key(ecdsa, q) != 1) { goto error; } hostkey->type = type; hostkey->ecdsa = ecdsa; break; case KEY_ED25519: pk = buffer_get_string(&data, &len); if (pk == NULL) goto error; if (len != ED25519_PK_SZ) goto error; hostkey->type = type; hostkey->ed25519_pk = pk; pk = NULL; break; default: // unknown key goto error; } return (hostkey); error: if (rsa != NULL) RSA_free(rsa); if (dsa != NULL) DSA_free(dsa); if (ecdsa != NULL) EC_KEY_free(ecdsa); free(hostkey); return NULL; }
int dtls_connection_init(struct packet_stream *ps, int active, struct dtls_cert *cert) { struct dtls_connection *d; unsigned long err; if (!ps || !ps->sfd) return 0; __DBG("dtls_connection_init(%i)", active); d = &ps->sfd->dtls; if (d->init) { if ((d->active && active) || (!d->active && !active)) goto done; dtls_connection_cleanup(d); } d->ssl_ctx = SSL_CTX_new(active ? DTLSv1_client_method() : DTLSv1_server_method()); if (!d->ssl_ctx) goto error; if (SSL_CTX_use_certificate(d->ssl_ctx, cert->x509) != 1) goto error; if (SSL_CTX_use_PrivateKey(d->ssl_ctx, cert->pkey) != 1) goto error; SSL_CTX_set_verify(d->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); SSL_CTX_set_verify_depth(d->ssl_ctx, 4); SSL_CTX_set_cipher_list(d->ssl_ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); if (SSL_CTX_set_tlsext_use_srtp(d->ssl_ctx, ciphers_str)) goto error; if (SSL_CTX_set_read_ahead(d->ssl_ctx, 1)) goto error; d->ssl = SSL_new(d->ssl_ctx); if (!d->ssl) goto error; d->r_bio = BIO_new(BIO_s_mem()); d->w_bio = BIO_new(BIO_s_mem()); if (!d->r_bio || !d->w_bio) goto error; SSL_set_app_data(d->ssl, ps->sfd); /* XXX obj reference here? */ SSL_set_bio(d->ssl, d->r_bio, d->w_bio); SSL_set_mode(d->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (ecdh == NULL) goto error; SSL_set_options(d->ssl, SSL_OP_SINGLE_ECDH_USE); SSL_set_tmp_ecdh(d->ssl, ecdh); EC_KEY_free(ecdh); d->init = 1; d->active = active ? -1 : 0; done: return 0; error: err = ERR_peek_last_error(); if (d->r_bio) BIO_free(d->r_bio); if (d->w_bio) BIO_free(d->w_bio); if (d->ssl) SSL_free(d->ssl); if (d->ssl_ctx) SSL_CTX_free(d->ssl_ctx); ZERO(*d); ilog(LOG_ERROR, "Failed to init DTLS connection: %s", ERR_reason_error_string(err)); return -1; }
static int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out) { EC_KEY *a = NULL; EC_KEY *b = NULL; BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL; char buf[12]; unsigned char *abuf = NULL, *bbuf = NULL; int i, alen, blen, aout, bout, ret = 0; const EC_GROUP *group; a = EC_KEY_new_by_curve_name(nid); b = EC_KEY_new_by_curve_name(nid); if (a == NULL || b == NULL) goto err; group = EC_KEY_get0_group(a); if ((x_a = BN_new()) == NULL) goto err; if ((y_a = BN_new()) == NULL) goto err; if ((x_b = BN_new()) == NULL) goto err; if ((y_b = BN_new()) == NULL) goto err; BIO_puts(out, "Testing key generation with "); BIO_puts(out, text); # ifdef NOISY BIO_puts(out, "\n"); # else (void)BIO_flush(out); # endif if (!EC_KEY_generate_key(a)) goto err; if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp (group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } # ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } # endif # ifdef NOISY BIO_puts(out, " pri 1="); BN_print(out, a->priv_key); BIO_puts(out, "\n pub 1="); BN_print(out, x_a); BIO_puts(out, ","); BN_print(out, y_a); BIO_puts(out, "\n"); # else BIO_printf(out, " ."); (void)BIO_flush(out); # endif if (!EC_KEY_generate_key(b)) goto err; if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp (group, EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err; } # ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err; } # endif # ifdef NOISY BIO_puts(out, " pri 2="); BN_print(out, b->priv_key); BIO_puts(out, "\n pub 2="); BN_print(out, x_b); BIO_puts(out, ","); BN_print(out, y_b); BIO_puts(out, "\n"); # else BIO_printf(out, "."); (void)BIO_flush(out); # endif alen = KDF1_SHA1_len; abuf = (unsigned char *)OPENSSL_malloc(alen); aout = ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1); # ifdef NOISY BIO_puts(out, " key1 ="); for (i = 0; i < aout; i++) { sprintf(buf, "%02X", abuf[i]); BIO_puts(out, buf); } BIO_puts(out, "\n"); # else BIO_printf(out, "."); (void)BIO_flush(out); # endif blen = KDF1_SHA1_len; bbuf = (unsigned char *)OPENSSL_malloc(blen); bout = ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1); # ifdef NOISY BIO_puts(out, " key2 ="); for (i = 0; i < bout; i++) { sprintf(buf, "%02X", bbuf[i]); BIO_puts(out, buf); } BIO_puts(out, "\n"); # else BIO_printf(out, "."); (void)BIO_flush(out); # endif if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) { # ifndef NOISY BIO_printf(out, " failed\n\n"); BIO_printf(out, "key a:\n"); BIO_printf(out, "private key: "); BN_print(out, EC_KEY_get0_private_key(a)); BIO_printf(out, "\n"); BIO_printf(out, "public key (x,y): "); BN_print(out, x_a); BIO_printf(out, ","); BN_print(out, y_a); BIO_printf(out, "\nkey b:\n"); BIO_printf(out, "private key: "); BN_print(out, EC_KEY_get0_private_key(b)); BIO_printf(out, "\n"); BIO_printf(out, "public key (x,y): "); BN_print(out, x_b); BIO_printf(out, ","); BN_print(out, y_b); BIO_printf(out, "\n"); BIO_printf(out, "generated key a: "); for (i = 0; i < bout; i++) { sprintf(buf, "%02X", bbuf[i]); BIO_puts(out, buf); } BIO_printf(out, "\n"); BIO_printf(out, "generated key b: "); for (i = 0; i < aout; i++) { sprintf(buf, "%02X", abuf[i]); BIO_puts(out, buf); } BIO_printf(out, "\n"); # endif fprintf(stderr, "Error in ECDH routines\n"); ret = 0; } else { # ifndef NOISY BIO_printf(out, " ok\n"); # endif ret = 1; } err: ERR_print_errors_fp(stderr); if (abuf != NULL) OPENSSL_free(abuf); if (bbuf != NULL) OPENSSL_free(bbuf); if (x_a) BN_free(x_a); if (y_a) BN_free(y_a); if (x_b) BN_free(x_b); if (y_b) BN_free(y_b); if (b) EC_KEY_free(b); if (a) EC_KEY_free(a); return (ret); }
CECKey::CECKey() { pkey = EC_KEY_new_by_curve_name(NID_secp256k1); assert(pkey != NULL); }
static int input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; EC_POINT *client_public; EC_KEY *server_key = NULL; const EC_GROUP *group; const EC_POINT *public_key; BIGNUM *shared_secret = NULL; struct sshkey *server_host_private, *server_host_public; u_char *server_host_key_blob = NULL, *signature = NULL; u_char *kbuf = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t slen, sbloblen; size_t klen = 0, hashlen; int r; if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (EC_KEY_generate_key(server_key) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } group = EC_KEY_get0_group(server_key); #ifdef DEBUG_KEXECDH fputs("server private key:\n", stderr); sshkey_dump_ec_key(server_key); #endif if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } server_host_public = kex->load_host_public_key(kex->hostkey_type, kex->hostkey_nid, ssh); server_host_private = kex->load_host_private_key(kex->hostkey_type, kex->hostkey_nid, ssh); if (server_host_public == NULL) { r = SSH_ERR_NO_HOSTKEY_LOADED; goto out; } if ((client_public = EC_POINT_new(group)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshpkt_get_ec(ssh, client_public, group)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; #ifdef DEBUG_KEXECDH fputs("client public key:\n", stderr); sshkey_dump_ec_point(group, client_public); #endif if (sshkey_ec_validate_public(group, client_public) != 0) { sshpkt_disconnect(ssh, "invalid client public key"); r = SSH_ERR_MESSAGE_INCOMPLETE; goto out; } /* Calculate shared_secret */ klen = (EC_GROUP_get_degree(group) + 7) / 8; if ((kbuf = malloc(klen)) == NULL || (shared_secret = BN_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (ECDH_compute_key(kbuf, klen, client_public, server_key, NULL) != (int)klen || BN_bin2bn(kbuf, klen, shared_secret) == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } #ifdef DEBUG_KEXECDH dump_digest("shared secret", kbuf, klen); #endif /* calc H */ if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, &sbloblen)) != 0) goto out; hashlen = sizeof(hash); if ((r = kex_ecdh_hash( kex->hash_alg, group, kex->client_version_string, kex->server_version_string, sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, client_public, EC_KEY_get0_public_key(server_key), shared_secret, hash, &hashlen)) != 0) goto out; /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; kex->session_id = malloc(kex->session_id_len); if (kex->session_id == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ if ((r = kex->sign(server_host_private, server_host_public, &signature, &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) goto out; /* destroy_sensitive_data(); */ public_key = EC_KEY_get0_public_key(server_key); /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 || (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || (r = sshpkt_put_ec(ssh, public_key, group)) != 0 || (r = sshpkt_put_string(ssh, signature, slen)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); if (kex->ec_client_key) { EC_KEY_free(kex->ec_client_key); kex->ec_client_key = NULL; } if (server_key) EC_KEY_free(server_key); if (kbuf) { explicit_bzero(kbuf, klen); free(kbuf); } if (shared_secret) BN_clear_free(shared_secret); free(server_host_key_blob); free(signature); return r; }
static void setup_ecc_key(SSL_CTX *ssl_ctx) { EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); SSL_CTX_set_tmp_ecdh(ssl_ctx, key); EC_KEY_free(key); }
/* Verify the signature on this transaction using the public key * prev_tx->dest_pubkey. The return value is: * 1 for successful verification; * 0 for failed verification; * -1 for any runtime error. */ int transaction_verify(struct transaction *tx, const struct transaction *prev_tx) { unsigned char uint32_buf[4]; SHA256_CTX sha; hash_output h; EC_KEY *pubkey; ECDSA_SIG *sig; BIGNUM *x, *y; int v, rc; pubkey = NULL; sig = NULL; x = NULL; y = NULL; SHA256_Init(&sha); serialize_uint32(uint32_buf, tx->height); SHA256_Update(&sha, uint32_buf, sizeof(uint32_buf)); SHA256_Update(&sha, tx->prev_transaction_hash, sizeof(tx->prev_transaction_hash)); SHA256_Update(&sha, tx->dest_pubkey.x, sizeof(tx->dest_pubkey.x)); SHA256_Update(&sha, tx->dest_pubkey.y, sizeof(tx->dest_pubkey.y)); SHA256_Final(h, &sha); x = BN_bin2bn(prev_tx->dest_pubkey.x, sizeof(prev_tx->dest_pubkey.x), NULL); if (x == NULL) goto err; y = BN_bin2bn(prev_tx->dest_pubkey.y, sizeof(prev_tx->dest_pubkey.y), NULL); if (y == NULL) goto err; pubkey = EC_KEY_new_by_curve_name(EC_GROUP_NID); if (pubkey == NULL) goto err; rc = EC_KEY_set_public_key_affine_coordinates(pubkey, x, y); if (rc != 1) { EC_KEY_free(pubkey); BN_free(x); BN_free(y); return 0; } BN_free(x); x = NULL; BN_free(y); y = NULL; sig = ECDSA_SIG_new(); if (sig == NULL) goto err; sig->r = BN_bin2bn(tx->src_signature.r, sizeof(tx->src_signature.r), sig->r); if (sig->r == NULL) goto err; sig->s = BN_bin2bn(tx->src_signature.s, sizeof(tx->src_signature.s), sig->s); if (sig->s == NULL) goto err; v = ECDSA_do_verify(h, sizeof(h), sig, pubkey); EC_KEY_free(pubkey); ECDSA_SIG_free(sig); return v; err: if (pubkey != NULL) EC_KEY_free(pubkey); if (sig != NULL) ECDSA_SIG_free(sig); if (x != NULL) BN_free(x); if (y != NULL) BN_free(y); return -1; }
eventer_ssl_ctx_t * eventer_ssl_ctx_new(eventer_ssl_orientation_t type, const char *layer, const char *certificate, const char *key, const char *ca, const char *ciphers) { char ssl_ctx_key[SSL_CTX_KEYLEN]; eventer_ssl_ctx_t *ctx; const char *layer_str; char *ctx_layer, *opts; char *opts_fallback = DEFAULT_OPTS_STRING; time_t now; ctx = calloc(1, sizeof(*ctx)); if(!ctx) return NULL; layer_str = layer ? layer : DEFAULT_LAYER_STRING; ctx_layer = alloca(strlen(layer_str)+1); memcpy(ctx_layer, layer_str, strlen(layer_str)+1); opts = strchr(ctx_layer,':'); if(opts) *opts++ = '\0'; else { opts = alloca(strlen(opts_fallback)+1); memcpy(opts, opts_fallback, strlen(opts_fallback)+1); } now = time(NULL); ssl_ctx_key_write(ssl_ctx_key, sizeof(ssl_ctx_key), type, layer, certificate, key, ca, ciphers); ctx->ssl_ctx_cn = ssl_ctx_cache_get(ssl_ctx_key); if(ctx->ssl_ctx_cn) { if(now - ctx->ssl_ctx_cn->creation_time > ssl_ctx_cache_expiry || (now - ctx->ssl_ctx_cn->last_stat_time > ssl_ctx_cache_finfo_expiry && (validate_finfo(&ctx->ssl_ctx_cn->cert_finfo, certificate) || validate_finfo(&ctx->ssl_ctx_cn->key_finfo, key) || validate_finfo(&ctx->ssl_ctx_cn->ca_finfo, ca) || (ctx->ssl_ctx_cn->last_stat_time = now) == 0))) { /* assignment */ ssl_ctx_cache_remove(ssl_ctx_key); ssl_ctx_cache_node_free(ctx->ssl_ctx_cn); ctx->ssl_ctx_cn = NULL; } } if(!ctx->ssl_ctx_cn) { char *part = NULL, *brkt = NULL; long ctx_options = 0; ssl_ctx_cache_node *existing_ctx_cn; ctx->ssl_ctx_cn = calloc(1, sizeof(*ctx->ssl_ctx_cn)); ctx->ssl_ctx_cn->key = strdup(ssl_ctx_key); ctx->ssl_ctx_cn->refcnt = 1; ctx->ssl_ctx_cn->creation_time = now; ctx->ssl_ctx_cn->last_stat_time = now; populate_finfo(&ctx->ssl_ctx_cn->cert_finfo, certificate); populate_finfo(&ctx->ssl_ctx_cn->key_finfo, key); populate_finfo(&ctx->ssl_ctx_cn->ca_finfo, ca); ctx->ssl_ctx = NULL; if(0) ; #if defined(SSL_TXT_SSLV3) && defined(HAVE_SSLV3_SERVER) && defined(HAVE_SSLV3_CLIENT) else if(layer && !strcasecmp(layer, SSL_TXT_SSLV3)) ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ? SSLv3_server_method() : SSLv3_client_method()); #endif #if defined(SSL_TXT_SSLV2) && defined(HAVE_SSLV2_SERVER) && defined(HAVE_SSLV2_CLIENT) else if(layer && !strcasecmp(layer, SSL_TXT_SSLV2)) ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ? SSLv2_server_method() : SSLv2_client_method()); #endif #if defined(SSL_TXT_TLSV1) && defined(HAVE_TLSV1_SERVER) && defined(HAVE_TLSV1_CLIENT) else if(layer && !strcasecmp(layer, SSL_TXT_TLSV1)) ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ? TLSv1_server_method() : TLSv1_client_method()); #endif #if defined(SSL_TXT_TLSV1_1) && defined(HAVE_TLSV1_1_SERVER) && defined(HAVE_TLSV1_1_CLIENT) else if(layer && !strcasecmp(layer, SSL_TXT_TLSV1_1)) ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ? TLSv1_1_server_method() : TLSv1_1_client_method()); #endif #if defined(SSL_TXT_TLSV1_2) && defined(HAVE_TLSV1_2_SERVER) && defined(HAVE_TLSV1_2_CLIENT) else if(layer && !strcasecmp(layer, SSL_TXT_TLSV1_2)) ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ? TLSv1_2_server_method() : TLSv1_2_client_method()); #endif if(ctx->ssl_ctx == NULL) ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ? SSLv23_server_method() : SSLv23_client_method()); if(!ctx->ssl_ctx) goto bail; for(part = strtok_r(opts, ",", &brkt); part; part = strtok_r(NULL, ",", &brkt)) { char *optname = part; int neg = 0; if(*optname == '!') neg = 1, optname++; #define SETBITOPT(name, neg, opt) \ if(!strcasecmp(optname, name)) { \ if(neg) ctx_options &= ~(opt); \ else ctx_options |= (opt); \ } SETBITOPT("all", neg, SSL_OP_ALL) #ifdef SSL_TXT_SSLV2 else SETBITOPT(SSL_TXT_SSLV2, !neg, SSL_OP_NO_SSLv2) #endif #ifdef SSL_TXT_SSLV3 else SETBITOPT(SSL_TXT_SSLV3, !neg, SSL_OP_NO_SSLv3) #endif #ifdef SSL_TXT_TLSV1 else SETBITOPT(SSL_TXT_TLSV1, !neg, SSL_OP_NO_TLSv1) #endif #ifdef SSL_TXT_TLSV1_1 else SETBITOPT(SSL_TXT_TLSV1_1, !neg, SSL_OP_NO_TLSv1_1) #endif #ifdef SSL_TXT_TLSV1_2 else SETBITOPT(SSL_TXT_TLSV1_2, !neg, SSL_OP_NO_TLSv1_2) #endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE else SETBITOPT("cipher_server_preference", neg, SSL_OP_CIPHER_SERVER_PREFERENCE) #endif else { mtevL(mtev_error, "SSL layer part '%s' not understood.\n", optname); } } if (type == SSL_SERVER) SSL_CTX_set_session_id_context(ctx->ssl_ctx, (unsigned char *)EVENTER_SSL_DATANAME, sizeof(EVENTER_SSL_DATANAME)-1); #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; #endif #ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG ctx_options &= ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; #endif #ifdef SSL_OP_NO_COMPRESSION ctx_options |= SSL_OP_NO_COMPRESSION; #endif #ifdef SSL_OP_NO_TICKET ctx_options |= SSL_OP_NO_TICKET; #endif #ifdef SSL_OP_SINGLE_DH_USE ctx_options |= SSL_OP_SINGLE_DH_USE; #endif #ifdef SSL_OP_SINGLE_ECDH_USE ctx_options |= SSL_OP_SINGLE_ECDH_USE; #endif SSL_CTX_set_options(ctx->ssl_ctx, ctx_options); #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(ctx->ssl_ctx, SSL_MODE_RELEASE_BUFFERS); #endif if(certificate && SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, certificate) != 1) goto bail; if(key && SSL_CTX_use_RSAPrivateKey_file(ctx->ssl_ctx,key, SSL_FILETYPE_PEM) != 1) goto bail; if(ca) { STACK_OF(X509_NAME) *cert_stack; if(!SSL_CTX_load_verify_locations(ctx->ssl_ctx,ca,NULL) || (cert_stack = SSL_load_client_CA_file(ca)) == NULL) goto bail; SSL_CTX_set_client_CA_list(ctx->ssl_ctx, cert_stack); } SSL_CTX_set_cipher_list(ctx->ssl_ctx, ciphers ? ciphers : "DEFAULT"); SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, verify_cb); #ifndef OPENSSL_NO_EC #if defined(SSL_CTX_set_ecdh_auto) SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1); #elif defined(NID_X9_62_prime256v1) EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); SSL_CTX_set_tmp_ecdh(ctx->ssl_ctx, ec_key); EC_KEY_free(ec_key); #endif #endif existing_ctx_cn = ssl_ctx_cache_set(ctx->ssl_ctx_cn); if(existing_ctx_cn != ctx->ssl_ctx_cn) { ssl_ctx_cache_node_free(ctx->ssl_ctx_cn); ctx->ssl_ctx_cn = existing_ctx_cn; } }
rb_ssl_ctx * rb_setup_ssl_server(const char *cacert, const char *cert, const char *keyfile, const char *dhfile, const char *ssl_cipher_list, const char *named_curve, rb_tls_ver_t tls_min_ver) { const char *libratbox_data = "libratbox tls session"; const char *ciphers = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL"; unsigned long err; rb_ssl_ctx *sctx; long tls_opts; sctx = rb_malloc(sizeof(rb_ssl_ctx)); sctx->refcount = 1; sctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if(sctx->ssl_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s", ERR_error_string(ERR_get_error(), NULL)); rb_free(sctx); return NULL; } tls_opts = SSL_CTX_get_options(sctx->ssl_ctx); /* Disable SSLv2, make the client use our settings */ tls_opts |= SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION | SSL_OP_CIPHER_SERVER_PREFERENCE; switch(tls_min_ver) { case RB_TLS_VER_SSL3: /* we default to SSLv3..sadly */ break; case RB_TLS_VER_TLS1: #ifdef SSL_OP_NO_SSLv3 tls_opts |= SSL_OP_NO_SSLv3; #endif break; case RB_TLS_VER_TLS1_1: #ifdef SSL_OP_NO_TLSv1 tls_opts |= SSL_OP_NO_TLSv1; #endif break; case RB_TLS_VER_TLS1_2: #ifdef SSL_OP_NO_TLSv1 tls_opts |= SSL_OP_NO_TLSv1; #endif #ifdef SSL_OP_NO_TLSv1_1 tls_opts |= SSL_OP_NO_TLSv1_1; #endif break; case RB_TLS_VER_LAST: break; } #ifdef SSL_OP_SINGLE_DH_USE tls_opts |= SSL_OP_SINGLE_DH_USE; #endif #ifdef SSL_OP_SINGLE_ECDH_USE tls_opts |= SSL_OP_SINGLE_ECDH_USE; #endif #ifdef SSL_OP_NO_TICKET tls_opts |= SSL_OP_NO_TICKET; #endif SSL_CTX_set_options(sctx->ssl_ctx, tls_opts); if(ssl_cipher_list != NULL) ciphers = ssl_cipher_list; if(!SSL_CTX_set_cipher_list(sctx->ssl_ctx, ciphers)) { rb_lib_log("rb_setup_ssl_server: Error setting ssl_cipher_list=\"%s\": %s", ciphers, ERR_error_string(ERR_get_error(), NULL)); goto cleanup;; } if(cert == NULL) { rb_lib_log("rb_setup_ssl_server: No certificate file"); goto cleanup; } if(!SSL_CTX_use_certificate_chain_file(sctx->ssl_ctx, cert)) { err = ERR_get_error(); rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", cert, ERR_error_string(err, NULL)); goto cleanup; } if(cacert != NULL) { if (!SSL_CTX_load_verify_locations(sctx->ssl_ctx, cacert, NULL)) { err = ERR_get_error(); rb_lib_log("rb_setup_ssl_server: Error loading CA file [%s]: %s", cacert, ERR_error_string(err, NULL)); goto cleanup; } } if(keyfile == NULL) { rb_lib_log("rb_setup_ssl_server: No key file"); goto cleanup; } if(!SSL_CTX_use_PrivateKey_file(sctx->ssl_ctx, keyfile, SSL_FILETYPE_PEM)) { err = ERR_get_error(); rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile, ERR_error_string(err, NULL)); goto cleanup;; } if(dhfile != NULL) { /* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */ BIO *bio = BIO_new_file(dhfile, "r"); if(bio != NULL) { DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); if(dh == NULL) { err = ERR_get_error(); rb_lib_log ("rb_setup_ssl_server: Error loading DH params file [%s]: %s", dhfile, ERR_error_string(err, NULL)); BIO_free(bio); goto cleanup; } BIO_free(bio); SSL_CTX_set_tmp_dh(sctx->ssl_ctx, dh); DH_free(dh); } else { err = ERR_get_error(); rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s", dhfile, ERR_error_string(err, NULL)); goto cleanup; } } #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH if(named_curve != NULL) { int nid; EC_KEY *ecdh; nid = OBJ_sn2nid(named_curve); if(nid == 0) { err = ERR_get_error(); rb_lib_log("rb_setup_ssl_server: Unknown curve named [%s]: %s", named_curve, ERR_error_string(err, NULL)); goto cleanup; } ecdh = EC_KEY_new_by_curve_name(nid); if(ecdh == NULL) { err = ERR_get_error(); rb_lib_log("rb_setup_ssl_server: Curve creation failed for [%s]: %s", named_curve, ERR_error_string(err, NULL)); goto cleanup; } SSL_CTX_set_options(sctx->ssl_ctx, SSL_OP_SINGLE_ECDH_USE); SSL_CTX_set_tmp_ecdh(sctx->ssl_ctx, ecdh); EC_KEY_free(ecdh); } #endif #endif SSL_CTX_set_verify(sctx->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); SSL_CTX_set_session_id_context(sctx->ssl_ctx, (const unsigned char *)libratbox_data, strlen(libratbox_data)); return sctx; cleanup: SSL_CTX_free(sctx->ssl_ctx); rb_free(sctx); return NULL; }
EC_KEY * vg_exec_context_new_key(void) { return EC_KEY_new_by_curve_name(NID_secp256k1); }