EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) { EVP_PKEY *ret=NULL; if (key == NULL) goto error; if (key->pkey != NULL) { return EVP_PKEY_dup(key->pkey); } if (key->public_key == NULL) goto error; if ((ret = EVP_PKEY_new()) == NULL) { OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, ERR_R_MALLOC_FAILURE); goto error; } if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm))) { OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_UNSUPPORTED_ALGORITHM); goto error; } if (ret->ameth->pub_decode) { if (!ret->ameth->pub_decode(ret, key)) { OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_PUBLIC_KEY_DECODE_ERROR); goto error; } } else { OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_METHOD_NOT_SUPPORTED); goto error; } /* Check to see if another thread set key->pkey first */ CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); if (key->pkey) { CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); EVP_PKEY_free(ret); ret = key->pkey; } else { key->pkey = ret; CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); } return EVP_PKEY_dup(ret); error: if (ret != NULL) EVP_PKEY_free(ret); return(NULL); }
static int TA_CTX_set_parameters(TA_CTX *ctx, const CVC_CERT *cert, BN_CTX *bn_ctx) { EVP_PKEY *pub; int ok = 0, oid; check(ctx && cert && cert->body && cert->body->public_key, "Invalid arguments"); /* Extract the public key of the terminal and overwrite the current key. */ if (ctx->priv_key) { pub = EVP_PKEY_dup(ctx->priv_key); check(CVC_pubkey2pkey(cert, bn_ctx, pub), "Failed to extract public key"); } else { /* ctx->pub might be NULL (in case of a CVCA certificate). */ pub = CVC_pubkey2pkey(cert, bn_ctx, ctx->pub_key); check(pub, "Failed to extract public key"); } ctx->pub_key = pub; /* Extract OID from the terminal certificate */ oid = OBJ_obj2nid(cert->body->public_key->oid); check(oid != NID_undef, "Unknown public key format"); /* Use the oid as the protocol identifier in the TA context */ ctx->protocol = oid; ok = 1; err: return ok; }
EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) { EVP_PKEY_CTX *rctx; if (!pctx->pmeth || !pctx->pmeth->copy) { return NULL; } rctx = OPENSSL_malloc(sizeof(EVP_PKEY_CTX)); if (!rctx) { return NULL; } memset(rctx, 0, sizeof(EVP_PKEY_CTX)); rctx->pmeth = pctx->pmeth; rctx->engine = pctx->engine; rctx->operation = pctx->operation; if (pctx->pkey) { rctx->pkey = EVP_PKEY_dup(pctx->pkey); if (rctx->pkey == NULL) { goto err; } } if (pctx->peerkey) { rctx->peerkey = EVP_PKEY_dup(pctx->peerkey); if (rctx->peerkey == NULL) { goto err; } } if (pctx->pmeth->copy(rctx, pctx) > 0) { return rctx; } err: EVP_PKEY_CTX_free(rctx); OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_dup, ERR_LIB_EVP); return NULL; }
KA_CTX * KA_CTX_dup(const KA_CTX *ka_ctx) { KA_CTX *out = NULL; check(ka_ctx, "Invalid arguments"); out = OPENSSL_malloc(sizeof(KA_CTX)); if (!out) goto err; out->key = EVP_PKEY_dup(ka_ctx->key); if (!out->key && ka_ctx->key) goto err; out->md = ka_ctx->md; out->md_engine = ka_ctx->md_engine; out->cmac_ctx = NULL; out->cipher = ka_ctx->cipher; out->cipher_engine = ka_ctx->cipher_engine; out->iv = NULL; out->generate_key = ka_ctx->generate_key; out->compute_key = ka_ctx->compute_key; out->mac_keylen = ka_ctx->mac_keylen; out->enc_keylen = ka_ctx->enc_keylen; if (ka_ctx->k_enc) { out->k_enc = BUF_MEM_create_init(ka_ctx->k_enc->data, ka_ctx->k_enc->length); if (!out->k_enc) goto err; } else out->k_enc = NULL; if (ka_ctx->k_mac) { out->k_mac = BUF_MEM_create_init(ka_ctx->k_mac->data, ka_ctx->k_mac->length); if (!out->k_mac) goto err; } else out->k_mac = NULL; if (ka_ctx->shared_secret) { out->shared_secret = BUF_MEM_create_init(ka_ctx->shared_secret->data, ka_ctx->shared_secret->length); if (!out->shared_secret) goto err; } else out->shared_secret = NULL; return out; err: KA_CTX_clear_free(out); return NULL; }
static EVP_PKEY_CTX *evp_pkey_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) { EVP_PKEY_CTX *ret; const EVP_PKEY_METHOD *pmeth; if (id == -1) { if (!pkey || !pkey->ameth) { return NULL; } id = pkey->ameth->pkey_id; } pmeth = evp_pkey_meth_find(id); if (pmeth == NULL) { OPENSSL_PUT_ERROR(EVP, evp_pkey_ctx_new, EVP_R_UNSUPPORTED_ALGORITHM); const char *name = OBJ_nid2sn(id); ERR_add_error_dataf("algorithm %d (%s)", id, name); return NULL; } ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX)); if (!ret) { OPENSSL_PUT_ERROR(EVP, evp_pkey_ctx_new, ERR_R_MALLOC_FAILURE); return NULL; } memset(ret, 0, sizeof(EVP_PKEY_CTX)); ret->engine = e; ret->pmeth = pmeth; ret->operation = EVP_PKEY_OP_UNDEFINED; if (pkey) { ret->pkey = EVP_PKEY_dup(pkey); } if (pmeth->init) { if (pmeth->init(ret) <= 0) { if (pkey) { EVP_PKEY_free(ret->pkey); } OPENSSL_free(ret); return NULL; } } return ret; }
static EVP_PKEY * EVP_PKEY_from_pubkey(EVP_PKEY *key, const BUF_MEM *pub, BN_CTX *bn_ctx) { EVP_PKEY *out = NULL; check(pub, "Invalid arguments"); out = EVP_PKEY_dup(key); check(out, ""); if (!EVP_PKEY_set_keys(out, NULL, 0, (const unsigned char *) pub->data, pub->length, bn_ctx)) { EVP_PKEY_free(out); out = NULL; goto err; } err: return out; }
CERT *ssl_cert_dup(CERT *cert) { CERT *ret; int i; ret = (CERT *)OPENSSL_malloc(sizeof(CERT)); if (ret == NULL) { OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE); return NULL; } memset(ret, 0, sizeof(CERT)); ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]]; /* or ret->key = ret->pkeys + (cert->key - cert->pkeys), if you find that * more readable */ ret->mask_k = cert->mask_k; ret->mask_a = cert->mask_a; if (cert->dh_tmp != NULL) { ret->dh_tmp = DHparams_dup(cert->dh_tmp); if (ret->dh_tmp == NULL) { OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_DH_LIB); goto err; } if (cert->dh_tmp->priv_key) { BIGNUM *b = BN_dup(cert->dh_tmp->priv_key); if (!b) { OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_BN_LIB); goto err; } ret->dh_tmp->priv_key = b; } if (cert->dh_tmp->pub_key) { BIGNUM *b = BN_dup(cert->dh_tmp->pub_key); if (!b) { OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_BN_LIB); goto err; } ret->dh_tmp->pub_key = b; } } ret->dh_tmp_cb = cert->dh_tmp_cb; if (cert->ecdh_tmp) { ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp); if (ret->ecdh_tmp == NULL) { OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_EC_LIB); goto err; } } ret->ecdh_tmp_cb = cert->ecdh_tmp_cb; ret->ecdh_tmp_auto = cert->ecdh_tmp_auto; for (i = 0; i < SSL_PKEY_NUM; i++) { CERT_PKEY *cpk = cert->pkeys + i; CERT_PKEY *rpk = ret->pkeys + i; if (cpk->x509 != NULL) { rpk->x509 = X509_up_ref(cpk->x509); } if (cpk->privatekey != NULL) { rpk->privatekey = EVP_PKEY_dup(cpk->privatekey); } if (cpk->chain) { rpk->chain = X509_chain_up_ref(cpk->chain); if (!rpk->chain) { OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE); goto err; } } } /* Peer sigalgs set to NULL as we get these from handshake too */ ret->peer_sigalgs = NULL; ret->peer_sigalgslen = 0; /* Configured sigalgs however we copy across */ if (cert->conf_sigalgs) { ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen); if (!ret->conf_sigalgs) { goto err; } memcpy(ret->conf_sigalgs, cert->conf_sigalgs, cert->conf_sigalgslen); ret->conf_sigalgslen = cert->conf_sigalgslen; } else { ret->conf_sigalgs = NULL; } if (cert->client_sigalgs) { ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen); if (!ret->client_sigalgs) { goto err; } memcpy(ret->client_sigalgs, cert->client_sigalgs, cert->client_sigalgslen); ret->client_sigalgslen = cert->client_sigalgslen; } else { ret->client_sigalgs = NULL; } /* Shared sigalgs also NULL */ ret->shared_sigalgs = NULL; /* Copy any custom client certificate types */ if (cert->client_certificate_types) { ret->client_certificate_types = BUF_memdup( cert->client_certificate_types, cert->num_client_certificate_types); if (!ret->client_certificate_types) { goto err; } ret->num_client_certificate_types = cert->num_client_certificate_types; } ret->cert_flags = cert->cert_flags; ret->cert_cb = cert->cert_cb; ret->cert_cb_arg = cert->cert_cb_arg; if (cert->verify_store) { CRYPTO_add(&cert->verify_store->references, 1, CRYPTO_LOCK_X509_STORE); ret->verify_store = cert->verify_store; } if (cert->chain_store) { CRYPTO_add(&cert->chain_store->references, 1, CRYPTO_LOCK_X509_STORE); ret->chain_store = cert->chain_store; } ret->ciphers_raw = NULL; return ret; err: ssl_cert_free(ret); return NULL; }
int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) { int ret; if (!ctx || !ctx->pmeth || !(ctx->pmeth->derive || ctx->pmeth->encrypt || ctx->pmeth->decrypt) || !ctx->pmeth->ctrl) { OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive_set_peer, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return 0; } if (ctx->operation != EVP_PKEY_OP_DERIVE && ctx->operation != EVP_PKEY_OP_ENCRYPT && ctx->operation != EVP_PKEY_OP_DECRYPT) { OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive_set_peer, EVP_R_OPERATON_NOT_INITIALIZED); return 0; } ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer); if (ret <= 0) { return 0; } if (ret == 2) { return 1; } if (!ctx->pkey) { OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive_set_peer, EVP_R_NO_KEY_SET); return 0; } if (ctx->pkey->type != peer->type) { OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive_set_peer, EVP_R_DIFFERENT_KEY_TYPES); return 0; } /* [email protected]: For clarity. The error is if parameters in peer are * present (!missing) but don't match. EVP_PKEY_cmp_parameters may return * 1 (match), 0 (don't match) and -2 (comparison is not defined). -1 * (different key types) is impossible here because it is checked earlier. * -2 is OK for us here, as well as 1, so we can check for 0 only. */ if (!EVP_PKEY_missing_parameters(peer) && !EVP_PKEY_cmp_parameters(ctx->pkey, peer)) { OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive_set_peer, EVP_R_DIFFERENT_PARAMETERS); return 0; } if (ctx->peerkey) { EVP_PKEY_free(ctx->peerkey); } ctx->peerkey = peer; ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer); if (ret <= 0) { ctx->peerkey = NULL; return 0; } EVP_PKEY_dup(peer); return 1; }