summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2019-11-02 20:26:42 +0000
committerDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2019-11-02 20:26:42 +0000
commit416b1922ffb912b1f11a20f7a533b7619291eaa0 (patch)
tree4a21f5f6e66a09676ff04889282dd5efbe6155fa
parente034c5f722d68c69d7e584111a95079bf4d66a33 (diff)
parent825458f482a7d398bc1e4df4a817747ed4232662 (diff)
downloadgnutls-416b1922ffb912b1f11a20f7a533b7619291eaa0.tar.gz
Merge branch 'crt-vrfy-final' into 'master'
tls-sig: reverse bytes in TLS signatures for GOST signatures See merge request gnutls/gnutls!1114
-rw-r--r--lib/algorithms.h1
-rw-r--r--lib/algorithms/sign.c3
-rw-r--r--lib/tls-sig.c47
3 files changed, 50 insertions, 1 deletions
diff --git a/lib/algorithms.h b/lib/algorithms.h
index a83fec07bb..60556a9a96 100644
--- a/lib/algorithms.h
+++ b/lib/algorithms.h
@@ -338,6 +338,7 @@ int _gnutls_version_mark_disabled(const char *name);
gnutls_protocol_t _gnutls_protocol_get_id_if_supported(const char *name);
#define GNUTLS_SIGN_FLAG_TLS13_OK 1 /* if it is ok to use under TLS1.3 */
+#define GNUTLS_SIGN_FLAG_CRT_VRFY_REVERSE (1 << 1) /* reverse order of bytes in CrtVrfy signature */
struct gnutls_sign_entry_st {
const char *name;
const char *oid;
diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c
index 6e4393b5dc..167c5fb51b 100644
--- a/lib/algorithms/sign.c
+++ b/lib/algorithms/sign.c
@@ -353,6 +353,7 @@ gnutls_sign_entry_st sign_algorithms[] = {
.id = GNUTLS_SIGN_GOST_512,
.pk = GNUTLS_PK_GOST_12_512,
.hash = GNUTLS_DIG_STREEBOG_512,
+ .flags = GNUTLS_SIGN_FLAG_CRT_VRFY_REVERSE,
.aid = {{8, 65}, SIG_SEM_PRE_TLS12}},
/* GOST R 34.10-2012-256 */
{.name = "GOSTR341012-256",
@@ -360,6 +361,7 @@ gnutls_sign_entry_st sign_algorithms[] = {
.id = GNUTLS_SIGN_GOST_256,
.pk = GNUTLS_PK_GOST_12_256,
.hash = GNUTLS_DIG_STREEBOG_256,
+ .flags = GNUTLS_SIGN_FLAG_CRT_VRFY_REVERSE,
.aid = {{8, 64}, SIG_SEM_PRE_TLS12}},
/* GOST R 34.10-2001 */
{.name = "GOSTR341001",
@@ -367,6 +369,7 @@ gnutls_sign_entry_st sign_algorithms[] = {
.id = GNUTLS_SIGN_GOST_94,
.pk = GNUTLS_PK_GOST_01,
.hash = GNUTLS_DIG_GOSTR_94,
+ .flags = GNUTLS_SIGN_FLAG_CRT_VRFY_REVERSE,
.aid = TLS_SIGN_AID_UNKNOWN},
/* GOST R 34.10-94 */
{.name = "GOSTR341094",
diff --git a/lib/tls-sig.c b/lib/tls-sig.c
index aebd0b1e3f..80514430ab 100644
--- a/lib/tls-sig.c
+++ b/lib/tls-sig.c
@@ -351,6 +351,34 @@ _gnutls_handshake_verify_data(gnutls_session_t session,
/* Client certificate verify calculations
*/
+static void
+_gnutls_reverse_datum(gnutls_datum_t * d)
+{
+ unsigned i;
+
+ for (i = 0; i < d->size / 2; i ++) {
+ uint8_t t = d->data[i];
+ d->data[i] = d->data[d->size - 1 - i];
+ d->data[d->size - 1 - i] = t;
+ }
+}
+
+static int
+_gnutls_create_reverse(const gnutls_datum_t *src, gnutls_datum_t *dst)
+{
+ unsigned int i;
+
+ dst->size = src->size;
+ dst->data = gnutls_malloc(dst->size);
+ if (!dst->data)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ for (i = 0; i < dst->size; i++)
+ dst->data[i] = src->data[dst->size - 1 - i];
+
+ return 0;
+}
+
/* this is _gnutls_handshake_verify_crt_vrfy for TLS 1.2
*/
static int
@@ -363,6 +391,7 @@ _gnutls_handshake_verify_crt_vrfy12(gnutls_session_t session,
int ret;
gnutls_datum_t dconcat;
const gnutls_sign_entry_st *se = _gnutls_sign_to_entry(sign_algo);
+ gnutls_datum_t sig_rev = {NULL, 0};
ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
if (ret < 0)
@@ -374,6 +403,12 @@ _gnutls_handshake_verify_crt_vrfy12(gnutls_session_t session,
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
}
+ if (se->flags & GNUTLS_SIGN_FLAG_CRT_VRFY_REVERSE) {
+ ret = _gnutls_create_reverse(signature, &sig_rev);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ }
+
dconcat.data = session->internals.handshake_hash_buffer.data;
dconcat.size = session->internals.handshake_hash_buffer_prev_len;
@@ -381,7 +416,9 @@ _gnutls_handshake_verify_crt_vrfy12(gnutls_session_t session,
* because we have checked whether the currently used signature
* algorithm is allowed in the session. */
ret = gnutls_pubkey_verify_data2(cert->pubkey, sign_algo, verify_flags|GNUTLS_VERIFY_ALLOW_BROKEN,
- &dconcat, signature);
+ &dconcat,
+ sig_rev.data ? &sig_rev : signature);
+ _gnutls_free_datum(&sig_rev);
if (ret < 0)
gnutls_assert();
@@ -587,6 +624,7 @@ _gnutls_handshake_sign_crt_vrfy12(gnutls_session_t session,
{
gnutls_datum_t dconcat;
gnutls_sign_algorithm_t sign_algo;
+ const gnutls_sign_entry_st *se;
int ret;
sign_algo = _gnutls_session_get_sign_algo(session, cert, pkey, 1);
@@ -595,6 +633,10 @@ _gnutls_handshake_sign_crt_vrfy12(gnutls_session_t session,
return GNUTLS_E_UNWANTED_ALGORITHM;
}
+ se = _gnutls_sign_to_entry(sign_algo);
+ if (se == NULL)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
gnutls_sign_algorithm_set_client(session, sign_algo);
if (unlikely(gnutls_sign_supports_pk_algorithm(sign_algo, pkey->pk_algorithm) == 0))
@@ -613,6 +655,9 @@ _gnutls_handshake_sign_crt_vrfy12(gnutls_session_t session,
return ret;
}
+ if (se->flags & GNUTLS_SIGN_FLAG_CRT_VRFY_REVERSE)
+ _gnutls_reverse_datum(signature);
+
return sign_algo;
}