Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/boringssl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Benjamin <davidben@chromium.org>2014-07-09 23:22:43 +0400
committerAdam Langley <agl@google.com>2014-07-10 04:05:14 +0400
commit0e2908a8069df529cb588611b451185bed601979 (patch)
treeb9c2d625da8167d8b1d4350a0c47e920adfb5f6d
parent636293bf25a4ef2c0e47b23cbfd1f8180d2c2d9f (diff)
Unify signing codepath of ssl3_send_client_verify.
Instead of, in the pre-TLS-1.2 case, reaching into the EVP and manually signing, compute the digest separately from signing. Then use EVP_PKEY_sign. This will make it easier to implement https://crbug.com/347404 by having only one signing codepath as well as make that logic simpler. Also add a bounds check while we're here, although the buffer is too large to actually matter. runner.go client auth tests should cover code changes. Change-Id: I7d87181bbcc5a761660412452e508d24c4725327 Reviewed-on: https://boringssl-review.googlesource.com/1122 Reviewed-by: Adam Langley <agl@google.com>
-rw-r--r--ssl/s3_clnt.c127
1 files changed, 66 insertions, 61 deletions
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 6f6cf3d9..5f3e997e 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -2674,28 +2674,32 @@ err:
int ssl3_send_client_verify(SSL *s)
{
- unsigned char *p;
- unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
+ unsigned char *buf, *p;
+ const EVP_MD *md;
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ unsigned digest_length;
EVP_PKEY *pkey;
EVP_PKEY_CTX *pctx = NULL;
EVP_MD_CTX mctx;
- unsigned signature_length = 0;
- unsigned long n;
+ size_t signature_length = 0;
+ unsigned long n = 0;
EVP_MD_CTX_init(&mctx);
+ buf=(unsigned char *)s->init_buf->data;
if (s->state == SSL3_ST_CW_CERT_VRFY_A)
{
p= ssl_handshake_start(s);
pkey = s->cert->key->privatekey;
- /* For TLS v1.2 send signature algorithm and signature
- * using agreed digest and cached handshake records.
+ /* For TLS v1.2 send signature algorithm and signature using
+ * agreed digest and cached handshake records. Otherwise, use
+ * SHA1 or MD5 + SHA1 depending on key type.
*/
if (SSL_USE_SIGALGS(s))
{
long hdatalen = 0;
char *hdata;
- const EVP_MD *md = s->cert->key->digest;
+ md = s->cert->key->digest;
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,
&hdata);
if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md))
@@ -2704,76 +2708,77 @@ int ssl3_send_client_verify(SSL *s)
goto err;
}
p += 2;
-#ifdef SSL_DEBUG
- fprintf(stderr, "Using TLS 1.2 with client alg %s\n",
- EVP_MD_name(md));
-#endif
- if (!EVP_SignInit_ex(&mctx, md, NULL)
- || !EVP_SignUpdate(&mctx, hdata, hdatalen)
- || !EVP_SignFinal(&mctx, p + 2,
- &signature_length, pkey))
+ n += 2;
+ if (!EVP_DigestInit_ex(&mctx, md, NULL)
+ || !EVP_DigestUpdate(&mctx, hdata, hdatalen)
+ || !EVP_DigestFinal(&mctx, digest, &digest_length))
{
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_EVP_LIB);
goto err;
}
- s2n(signature_length, p);
- n = signature_length + 4;
- if (!ssl3_digest_cached_records(s))
- goto err;
}
- else
- if (pkey->type == EVP_PKEY_RSA)
+ else if (pkey->type == EVP_PKEY_RSA)
{
- s->method->ssl3_enc->cert_verify_mac(s, NID_md5, data);
+ s->method->ssl3_enc->cert_verify_mac(s, NID_md5, digest);
s->method->ssl3_enc->cert_verify_mac(s,
- NID_sha1, &data[MD5_DIGEST_LENGTH]);
- if (RSA_sign(NID_md5_sha1, data,
- MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
- &p[2], &signature_length, pkey->pkey.rsa) <= 0)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_RSA_LIB);
- goto err;
- }
- s2n(signature_length, p);
- n = signature_length + 2;
+ NID_sha1, &digest[MD5_DIGEST_LENGTH]);
+ digest_length = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
+ /* Using a NULL signature MD makes EVP_PKEY_sign perform
+ * a raw RSA signature, rather than wrapping in a
+ * DigestInfo. */
+ md = NULL;
}
- else
-#ifndef OPENSSL_NO_DSA
- if (pkey->type == EVP_PKEY_DSA)
+ else if (pkey->type == EVP_PKEY_DSA || pkey->type == EVP_PKEY_EC)
{
- s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, data);
- if (!DSA_sign(pkey->save_type, data,
- SHA_DIGEST_LENGTH, &(p[2]),
- &signature_length, pkey->pkey.dsa))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_DSA_LIB);
- goto err;
- }
- s2n(signature_length, p);
- n = signature_length + 2;
+ s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, digest);
+ digest_length = SHA_DIGEST_LENGTH;
+ md = EVP_sha1();
}
else
-#endif
-#ifndef OPENSSL_NO_ECDSA
- if (pkey->type == EVP_PKEY_EC)
{
- s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, data);
- if (!ECDSA_sign(pkey->save_type, data,
- SHA_DIGEST_LENGTH, &(p[2]),
- &signature_length, pkey->pkey.ec))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_ECDSA_LIB);
- goto err;
- }
- s2n(signature_length, p);
- n = signature_length + 2;
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_INTERNAL_ERROR);
+ goto err;
}
- else
-#endif
+
+ /* Sign the digest. */
+ pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (pctx == NULL)
+ goto err;
+
+ /* Initialize the EVP_PKEY_CTX and determine the size of the signature. */
+ if (EVP_PKEY_sign_init(pctx) != 1 ||
+ EVP_PKEY_CTX_set_signature_md(pctx, md) != 1 ||
+ EVP_PKEY_sign(pctx, NULL, &signature_length,
+ digest, digest_length) != 1)
{
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_INTERNAL_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ if (p + 2 + signature_length > buf + SSL3_RT_MAX_PLAIN_LENGTH)
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, SSL_R_DATA_LENGTH_TOO_LONG);
goto err;
}
+
+ if (EVP_PKEY_sign(pctx, &p[2], &signature_length,
+ digest, digest_length) != 1)
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ s2n(signature_length, p);
+ n += signature_length + 2;
+
+ /* Now that client auth is completed, we no longer need cached
+ * handshake records and can digest them. */
+ if (SSL_USE_SIGALGS(s))
+ {
+ if (!ssl3_digest_cached_records(s))
+ goto err;
+ }
+
ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n);
s->state=SSL3_ST_CW_CERT_VRFY_B;
}