/* * Ensure the client has the private key by first decrypting the packet and * then checking the packet digests. */ static int process_cert_verify(SSL *ssl) { uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index]; int pkt_size = ssl->bm_index; uint8_t dgst_buf[MAX_KEY_BYTE_SIZE]; uint8_t dgst[MD5_SIZE+SHA1_SIZE]; X509_CTX *x509_ctx = ssl->x509_ctx; int ret = SSL_OK; int n; PARANOIA_CHECK(pkt_size, x509_ctx->rsa_ctx->num_octets+6); DISPLAY_RSA(ssl, x509_ctx->rsa_ctx); /* rsa_ctx->bi_ctx is not thread-safe */ SSL_CTX_LOCK(ssl->ssl_ctx->mutex); n = RSA_decrypt(x509_ctx->rsa_ctx, &buf[6], dgst_buf, 0); SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex); if (n != SHA1_SIZE + MD5_SIZE) { ret = SSL_ERROR_INVALID_KEY; goto end_cert_vfy; } finished_digest(ssl, NULL, dgst); /* calculate the digest */ if (memcmp(dgst_buf, dgst, MD5_SIZE + SHA1_SIZE)) { ret = SSL_ERROR_INVALID_KEY; } end_cert_vfy: ssl->next_state = HS_FINISHED; error: return ret; }
/* * Send a certificate verify message. */ static int send_cert_verify(SSL *ssl) { uint8_t *buf = ssl->bm_data; uint8_t dgst[MD5_SIZE+SHA1_SIZE]; RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx; int n = 0, ret; if (rsa_ctx == NULL) return SSL_OK; DISPLAY_RSA(ssl, rsa_ctx); buf[0] = HS_CERT_VERIFY; buf[1] = 0; finished_digest(ssl, NULL, dgst); /* calculate the digest */ /* rsa_ctx->bi_ctx is not thread-safe */ if (rsa_ctx) { SSL_CTX_LOCK(ssl->ssl_ctx->mutex); n = RSA_encrypt(rsa_ctx, dgst, sizeof(dgst), &buf[6], 1); SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex); if (n == 0) { ret = SSL_ERROR_INVALID_KEY; goto error; } } buf[4] = n >> 8; /* add the RSA size (not officially documented) */ buf[5] = n & 0xff; n += 2; buf[2] = n >> 8; buf[3] = n & 0xff; ret = send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, n+4); error: return ret; }
/* * Ensure the client has the private key by first decrypting the packet and * then checking the packet digests. */ static int process_cert_verify(SSL *ssl) { uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index]; int pkt_size = ssl->bm_index; uint8_t dgst_buf[MAX_KEY_BYTE_SIZE]; uint8_t dgst[MD5_SIZE + SHA1_SIZE]; X509_CTX *x509_ctx = ssl->x509_ctx; int ret = SSL_OK; int offset = 6; int rsa_len; int n; DISPLAY_RSA(ssl, x509_ctx->rsa_ctx); if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+ { // TODO: should really need to be able to handle other algorihms. An // assumption is made on RSA/SHA256 and appears to be OK. //uint8_t hash_alg = buf[4]; //uint8_t sig_alg = buf[5]; offset = 8; rsa_len = (buf[6] << 8) + buf[7]; } else { rsa_len = (buf[4] << 8) + buf[5]; } PARANOIA_CHECK(pkt_size, offset + rsa_len); /* rsa_ctx->bi_ctx is not thread-safe */ SSL_CTX_LOCK(ssl->ssl_ctx->mutex); n = RSA_decrypt(x509_ctx->rsa_ctx, &buf[offset], dgst_buf, sizeof(dgst_buf), 0); SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex); if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+ { if (memcmp(dgst_buf, g_asn1_sha256, sizeof(g_asn1_sha256))) { ret = SSL_ERROR_INVALID_KEY; goto error; } finished_digest(ssl, NULL, dgst); /* calculate the digest */ if (memcmp(&dgst_buf[sizeof(g_asn1_sha256)], dgst, SHA256_SIZE)) { ret = SSL_ERROR_INVALID_KEY; goto error; } } else // TLS1.0/1.1 { if (n != SHA1_SIZE + MD5_SIZE) { ret = SSL_ERROR_INVALID_KEY; goto end_cert_vfy; } finished_digest(ssl, NULL, dgst); /* calculate the digest */ if (memcmp(dgst_buf, dgst, MD5_SIZE + SHA1_SIZE)) { ret = SSL_ERROR_INVALID_KEY; } } end_cert_vfy: ssl->next_state = HS_FINISHED; error: return ret; }