X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssl_cert.c;h=a0da7d3741ac112fba250bac6b48168fcf9f2029;hp=2f43d2ede1437c1965cd09de8823fa826d7221a1;hb=1e2d4cb0e181ca6414b57c3e9a233bfa196d90a6;hpb=f71c6e52f769af0d2d40ed7e1dcb4fff837837a0 diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 2f43d2ede1..a0da7d3741 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -160,18 +160,18 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void) return ssl_x509_store_ctx_idx; } -static void ssl_cert_set_default_md(CERT *cert) +void ssl_cert_set_default_md(CERT *cert) { /* Set digest values to defaults */ #ifndef OPENSSL_NO_DSA - cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_dss1(); + cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1(); #endif #ifndef OPENSSL_NO_RSA cert->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1(); cert->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1(); #endif #ifndef OPENSSL_NO_ECDSA - cert->pkeys[SSL_PKEY_ECC].digest = EVP_ecdsa(); + cert->pkeys[SSL_PKEY_ECC].digest = EVP_sha1(); #endif } @@ -270,6 +270,7 @@ CERT *ssl_cert_dup(CERT *cert) } } ret->ecdh_tmp_cb = cert->ecdh_tmp_cb; + ret->ecdh_tmp_auto = cert->ecdh_tmp_auto; #endif for (i = 0; i < SSL_PKEY_NUM; i++) @@ -320,17 +321,29 @@ CERT *ssl_cert_dup(CERT *cert) if (cpk->chain) { - rpk->chain = sk_X509_dup(cpk->chain); + rpk->chain = X509_chain_up_ref(cpk->chain); if (!rpk->chain) { SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); goto err; } - for (i = 0; i < sk_X509_num(rpk->chain); i++) + } + rpk->valid_flags = 0; + if (cert->pkeys[i].authz != NULL) + { + /* Just copy everything. */ + ret->pkeys[i].authz_length = + cert->pkeys[i].authz_length; + ret->pkeys[i].authz = + OPENSSL_malloc(ret->pkeys[i].authz_length); + if (ret->pkeys[i].authz == NULL) { - X509 *x = sk_X509_value(rpk->chain, i); - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); + return(NULL); } + memcpy(ret->pkeys[i].authz, + cert->pkeys[i].authz, + cert->pkeys[i].authz_length); } } @@ -339,6 +352,64 @@ CERT *ssl_cert_dup(CERT *cert) * will be set during handshake. */ ssl_cert_set_default_md(ret); + /* 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->ctypes) + { + ret->ctypes = OPENSSL_malloc(cert->ctype_num); + if (!ret->ctypes) + goto err; + memcpy(ret->ctypes, cert->ctypes, cert->ctype_num); + ret->ctype_num = cert->ctype_num; + } + + 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); @@ -358,21 +429,44 @@ err: EC_KEY_free(ret->ecdh_tmp); #endif - for (i = 0; i < SSL_PKEY_NUM; i++) - { - CERT_PKEY *rpk = ret->pkeys + i; - if (rpk->x509 != NULL) - X509_free(rpk->x509); - if (rpk->privatekey != NULL) - EVP_PKEY_free(rpk->privatekey); - if (rpk->chain) - sk_X509_pop_free(rpk->chain, X509_free); - } - + ssl_cert_clear_certs(ret); return NULL; } +/* Free up and clear all certificates and chains */ + +void ssl_cert_clear_certs(CERT *c) + { + int i; + if (c == NULL) + return; + for (i = 0; ipkeys + i; + if (cpk->x509) + { + X509_free(cpk->x509); + cpk->x509 = NULL; + } + if (cpk->privatekey) + { + EVP_PKEY_free(cpk->privatekey); + cpk->privatekey = NULL; + } + if (cpk->chain) + { + sk_X509_pop_free(cpk->chain, X509_free); + cpk->chain = NULL; + } +#ifndef OPENSSL_NO_TLSEXT + if (cpk->authz != NULL) + OPENSSL_free(cpk->authz); +#endif + /* Clear all flags apart from explicit sign */ + cpk->valid_flags &= CERT_PKEY_EXPLICIT_SIGN; + } + } void ssl_cert_free(CERT *c) { @@ -404,20 +498,23 @@ void ssl_cert_free(CERT *c) if (c->ecdh_tmp) EC_KEY_free(c->ecdh_tmp); #endif - for (i=0; ipkeys + i; - if (cpk->x509 != NULL) - X509_free(cpk->x509); - if (cpk->privatekey != NULL) - EVP_PKEY_free(cpk->privatekey); - if (cpk->chain) - sk_X509_pop_free(cpk->chain, X509_free); -#if 0 - if (c->pkeys[i].publickey != NULL) - EVP_PKEY_free(c->pkeys[i].publickey); -#endif - } + ssl_cert_clear_certs(c); + if (c->peer_sigalgs) + OPENSSL_free(c->peer_sigalgs); + if (c->conf_sigalgs) + OPENSSL_free(c->conf_sigalgs); + if (c->client_sigalgs) + OPENSSL_free(c->client_sigalgs); + if (c->shared_sigalgs) + OPENSSL_free(c->shared_sigalgs); + if (c->ctypes) + OPENSSL_free(c->ctypes); + if (c->verify_store) + X509_STORE_free(c->verify_store); + if (c->chain_store) + X509_STORE_free(c->chain_store); + if (c->ciphers_raw) + OPENSSL_free(c->ciphers_raw); OPENSSL_free(c); } @@ -463,18 +560,11 @@ int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain) int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain) { STACK_OF(X509) *dchain; - X509 *x; - int i; if (!chain) return ssl_cert_set0_chain(c, NULL); - dchain = sk_X509_dup(chain); + dchain = X509_chain_up_ref(chain); if (!dchain) return 0; - for (i = 0; i < sk_X509_num(dchain); i++) - { - x = sk_X509_value(dchain, i); - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); - } if (!ssl_cert_set0_chain(c, dchain)) { sk_X509_pop_free(dchain, X509_free); @@ -503,6 +593,12 @@ int ssl_cert_add1_chain_cert(CERT *c, X509 *x) return 1; } +void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg) + { + c->cert_cb = cb; + c->cert_cb_arg = arg; + } + SESS_CERT *ssl_sess_cert_new(void) { SESS_CERT *ret; @@ -583,17 +679,25 @@ int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk) { X509 *x; int i; + X509_STORE *verify_store; X509_STORE_CTX ctx; + if (s->cert->verify_store) + verify_store = s->cert->verify_store; + else + verify_store = s->ctx->cert_store; + if ((sk == NULL) || (sk_X509_num(sk) == 0)) return(0); x=sk_X509_value(sk,0); - if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk)) + if(!X509_STORE_CTX_init(&ctx,verify_store,x,sk)) { SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB); return(0); } + /* Set suite B flags if needed */ + X509_STORE_CTX_set_flags(&ctx, tls1_suiteb(s)); #if 0 if (SSL_get_verify_depth(s) >= 0) X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s)); @@ -954,12 +1058,18 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l) X509 *x; STACK_OF(X509) *extra_certs; + X509_STORE *chain_store; if (cpk) x = cpk->x509; else x = NULL; + if (s->cert->chain_store) + chain_store = s->cert->chain_store; + else + chain_store = s->ctx->cert_store; + /* If we have a certificate specific chain use it, else use * parent ctx. */ @@ -990,7 +1100,7 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l) { X509_STORE_CTX xs_ctx; - if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL)) + if (!X509_STORE_CTX_init(&xs_ctx,chain_store,x,NULL)) { SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_X509_LIB); return(0); @@ -1002,7 +1112,7 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l) { x = sk_X509_value(xs_ctx.chain, i); - if (ssl_add_cert_to_buf(buf, l, x)) + if (!ssl_add_cert_to_buf(buf, l, x)) { X509_STORE_CTX_cleanup(&xs_ctx); return 0; @@ -1021,3 +1131,71 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l) return 1; } +/* Build a certificate chain for current certificate */ +int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags) + { + CERT_PKEY *cpk = c->key; + X509_STORE_CTX xs_ctx; + STACK_OF(X509) *chain = NULL, *untrusted = NULL; + X509 *x; + int i; + + if (!cpk->x509) + { + SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET); + return 0; + } + + if (c->chain_store) + chain_store = c->chain_store; + + if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED) + untrusted = cpk->chain; + + if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cpk->x509, untrusted)) + { + SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB); + return 0; + } + /* Set suite B flags if needed */ + X509_STORE_CTX_set_flags(&xs_ctx, c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS); + + i = X509_verify_cert(&xs_ctx); + if (i > 0) + chain = X509_STORE_CTX_get1_chain(&xs_ctx); + X509_STORE_CTX_cleanup(&xs_ctx); + if (i <= 0) + { + SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED); + return 0; + } + if (cpk->chain) + sk_X509_pop_free(cpk->chain, X509_free); + /* Remove EE certificate from chain */ + x = sk_X509_shift(chain); + X509_free(x); + if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) + { + x = sk_X509_pop(chain); + X509_free(x); + } + cpk->chain = chain; + + return 1; + } + +int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref) + { + X509_STORE **pstore; + if (chain) + pstore = &c->chain_store; + else + pstore = &c->verify_store; + if (*pstore) + X509_STORE_free(*pstore); + *pstore = store; + if (ref && store) + CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE); + return 1; + } +