Add X509_up_ref and use it internally.

Avoid needing to manually increment the reference count and using the right
lock, both here and in Chromium.

Change-Id: If116ebc224cfb1c4711f7e2c06f1fd2c97af21dd
Reviewed-on: https://boringssl-review.googlesource.com/1415
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c
index e626fcf..57e6167 100644
--- a/crypto/x509/x509_cmp.c
+++ b/crypto/x509/x509_cmp.c
@@ -508,8 +508,7 @@
 	ret = sk_X509_dup(chain);
 	for (i = 0; i < sk_X509_num(ret); i++)
 		{
-		X509 *x = sk_X509_value(ret, i);
-		CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+		X509_up_ref(sk_X509_value(ret, i));
 		}
 	return ret;
 	}
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index 63b81c3..05d1598 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -413,7 +413,7 @@
 	switch (a->type)
 		{
 	case X509_LU_X509:
-		CRYPTO_add(&a->data.x509->references,1,CRYPTO_LOCK_X509);
+		X509_up_ref(a->data.x509);
 		break;
 	case X509_LU_CRL:
 		CRYPTO_add(&a->data.crl->references,1,CRYPTO_LOCK_X509_CRL);
@@ -532,8 +532,7 @@
 		{
 		obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
 		x = obj->data.x509;
-		CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
-		if (!sk_X509_push(sk, x))
+		if (!sk_X509_push(sk, X509_up_ref(x)))
 			{
 			CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
 			X509_free(x);
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index fa5565b..18bb772 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -177,7 +177,7 @@
 			break;
 		}
 	if (i < sk_X509_num(certs))
-		CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
+		X509_up_ref(xtmp);
 	else
 		xtmp = NULL;
 	sk_X509_pop_free(certs, X509_free);
@@ -211,7 +211,7 @@
 			OPENSSL_PUT_ERROR(X509, X509_verify_cert, ERR_R_MALLOC_FAILURE);
 			goto end;
 			}
-		CRYPTO_add(&ctx->cert->references,1,CRYPTO_LOCK_X509);
+		X509_up_ref(ctx->cert);
 		ctx->last_untrusted=1;
 		}
 
@@ -494,7 +494,7 @@
 	*issuer = find_issuer(ctx, ctx->other_ctx, x);
 	if (*issuer)
 		{
-		CRYPTO_add(&(*issuer)->references,1,CRYPTO_LOCK_X509);
+		X509_up_ref(*issuer);
 		return 1;
 		}
 	else
diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c
index 712cff4..5cda3c7 100644
--- a/crypto/x509/x_x509.c
+++ b/crypto/x509/x_x509.c
@@ -136,6 +136,12 @@
 IMPLEMENT_ASN1_FUNCTIONS(X509)
 IMPLEMENT_ASN1_DUP_FUNCTION(X509)
 
+X509 *X509_up_ref(X509 *x)
+	{
+	CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+	return x;
+	}
+
 int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
         {
diff --git a/crypto/x509v3/pcy_tree.c b/crypto/x509v3/pcy_tree.c
index dbaa498..35567a7 100644
--- a/crypto/x509v3/pcy_tree.c
+++ b/crypto/x509v3/pcy_tree.c
@@ -258,8 +258,7 @@
 		level++;
 		x = sk_X509_value(certs, i);
 		cache = policy_cache_set(x);
-		CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
-		level->cert = x;
+		level->cert = X509_up_ref(x);
 
 		if (!cache->anyPolicy)
 				level->flags |= X509_V_FLAG_INHIBIT_ANY;
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index d07b2f5..058bbff 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -806,6 +806,10 @@
 
 DECLARE_ASN1_FUNCTIONS(X509_CERT_PAIR)
 
+/* X509_up_ref adds one to the reference count of |x| and returns
+ * |x|. */
+OPENSSL_EXPORT X509 *X509_up_ref(X509 *x);
+
 OPENSSL_EXPORT int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
 OPENSSL_EXPORT int X509_set_ex_data(X509 *r, int idx, void *arg);
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 1185873..fc1567f 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1180,18 +1180,16 @@
 		goto f_err;
 		}
 	sc->peer_cert_type=i;
-	CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
 	/* Why would the following ever happen?
 	 * We just created sc a couple of lines ago. */
 	if (sc->peer_pkeys[i].x509 != NULL)
 		X509_free(sc->peer_pkeys[i].x509);
-	sc->peer_pkeys[i].x509=x;
-	sc->peer_key= &(sc->peer_pkeys[i]);
+	sc->peer_pkeys[i].x509 = X509_up_ref(x);
+	sc->peer_key = &(sc->peer_pkeys[i]);
 
 	if (s->session->peer != NULL)
 		X509_free(s->session->peer);
-	CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
-	s->session->peer=x;
+	s->session->peer = X509_up_ref(x);
 
 	s->session->verify_result = s->verify_result;
 
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index c3994c4..7d398d9 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -261,8 +261,7 @@
 		CERT_PKEY *rpk = ret->pkeys + i;
 		if (cpk->x509 != NULL)
 			{
-			rpk->x509 = cpk->x509;
-			CRYPTO_add(&rpk->x509->references, 1, CRYPTO_LOCK_X509);
+			rpk->x509 = X509_up_ref(cpk->x509);
 			}
 		
 		if (cpk->privatekey != NULL)
@@ -365,14 +364,12 @@
 
 	if (cert->verify_store)
 		{
-		CRYPTO_add(&cert->verify_store->references, 1, CRYPTO_LOCK_X509_STORE);
-		ret->verify_store = cert->verify_store;
+		ret->verify_store = X509_up_ref(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->chain_store = X509_up_ref(cert->chain_store);
 		}
 
 	ret->ciphers_raw = NULL;
@@ -529,7 +526,7 @@
 	{
 	if (!ssl_cert_add0_chain_cert(c, x))
 		return 0;
-	CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+	X509_up_ref(x);
 	return 1;
 	}
 
@@ -1214,7 +1211,7 @@
 		X509_STORE_free(*pstore);
 	*pstore = store;
 	if (ref && store)
-		CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
+		X509_up_ref(store);
 	return 1;
 	}
 
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 9eace73..182b9eb 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -942,11 +942,10 @@
 	else
 		r=s->session->peer;
 
-	if (r == NULL) return(r);
+	if (r == NULL)
+		return NULL;
 
-	CRYPTO_add(&r->references,1,CRYPTO_LOCK_X509);
-
-	return(r);
+        return X509_up_ref(r);
 	}
 
 STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s)
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index 05163d4..7933863 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -443,8 +443,7 @@
 
 	if (c->pkeys[i].x509 != NULL)
 		X509_free(c->pkeys[i].x509);
-	CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
-	c->pkeys[i].x509=x;
+	c->pkeys[i].x509 = X509_up_ref(x);
 	c->key= &(c->pkeys[i]);
 
 	c->valid=0;