summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2016-11-29 05:28:17 +0300
committerDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2018-06-23 12:20:15 +0300
commitc77aa89206d633aa8218e245babb98ac195281e2 (patch)
tree4be34034bb21e5e108d07af0647929f250082364
parent05cd755fa46b0dfaa7aab9aa64627e41129fb7f7 (diff)
downloadgnutls-c77aa89206d633aa8218e245babb98ac195281e2.tar.gz
Add support for I/O of little-endian MPI
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
-rw-r--r--lib/crypto-backend.h4
-rw-r--r--lib/mpi.c82
-rw-r--r--lib/mpi.h4
-rw-r--r--lib/x509/x509_int.h5
4 files changed, 82 insertions, 13 deletions
diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h
index d57b1d1135..2930f055f5 100644
--- a/lib/crypto-backend.h
+++ b/lib/crypto-backend.h
@@ -94,7 +94,9 @@ typedef enum {
/* raw unsigned integer format */
GNUTLS_MPI_FORMAT_USG = 0,
/* raw signed integer format - always a leading zero when positive */
- GNUTLS_MPI_FORMAT_STD = 1
+ GNUTLS_MPI_FORMAT_STD = 1,
+ /* raw unsigned integer format, little endian format */
+ GNUTLS_MPI_FORMAT_ULE = 2
} gnutls_bigint_format_t;
/* Multi precision integer arithmetic */
diff --git a/lib/mpi.c b/lib/mpi.c
index afe1c0ea7d..5dbcfb4069 100644
--- a/lib/mpi.c
+++ b/lib/mpi.c
@@ -153,6 +153,28 @@ _gnutls_mpi_init_scan_nz(bigint_t * ret_mpi, const void *buffer, size_t nbytes)
return 0;
}
+int
+_gnutls_mpi_init_scan_le(bigint_t * ret_mpi, const void *buffer, size_t nbytes)
+{
+ bigint_t r;
+ int ret;
+
+ ret = _gnutls_mpi_init(&r);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_mpi_scan_le(r, buffer, nbytes);
+ if (ret < 0) {
+ gnutls_assert();
+ _gnutls_mpi_release(&r);
+ return ret;
+ }
+
+ *ret_mpi = r;
+
+ return 0;
+}
+
/* Always has the first bit zero */
int _gnutls_mpi_dprint_lz(const bigint_t a, gnutls_datum_t * dest)
{
@@ -248,13 +270,18 @@ _gnutls_mpi_dprint_size(const bigint_t a, gnutls_datum_t * dest,
return 0;
}
+/* Flags for __gnutls_x509_read_int() and __gnutls_x509_write_int */
+#define GNUTLS_X509_INT_OVERWRITE (1 << 0)
+#define GNUTLS_X509_INT_LE (1 << 1)
+#define GNUTLS_X509_INT_LZ (1 << 2) /* write only */
+
/* this function reads an integer
* from asn1 structs. Combines the read and mpi_scan
* steps.
*/
static int
__gnutls_x509_read_int(ASN1_TYPE node, const char *value,
- bigint_t * ret_mpi, int overwrite)
+ bigint_t * ret_mpi, unsigned int flags)
{
int result;
uint8_t *tmpstr = NULL;
@@ -280,9 +307,14 @@ __gnutls_x509_read_int(ASN1_TYPE node, const char *value,
return _gnutls_asn2err(result);
}
- result = _gnutls_mpi_init_scan(ret_mpi, tmpstr, tmpstr_size);
+ if (flags & GNUTLS_X509_INT_LE)
+ result = _gnutls_mpi_init_scan_le(ret_mpi, tmpstr,
+ tmpstr_size);
+ else
+ result = _gnutls_mpi_init_scan(ret_mpi, tmpstr,
+ tmpstr_size);
- if (overwrite)
+ if (flags & GNUTLS_X509_INT_OVERWRITE)
zeroize_key(tmpstr, tmpstr_size);
gnutls_free(tmpstr);
@@ -298,29 +330,42 @@ int
_gnutls_x509_read_int(ASN1_TYPE node, const char *value,
bigint_t * ret_mpi)
{
- return __gnutls_x509_read_int(node, value, ret_mpi, 0);
+ return __gnutls_x509_read_int(node, value, ret_mpi,
+ 0);
}
int
_gnutls_x509_read_key_int(ASN1_TYPE node, const char *value,
bigint_t * ret_mpi)
{
- return __gnutls_x509_read_int(node, value, ret_mpi, 1);
+ return __gnutls_x509_read_int(node, value, ret_mpi,
+ GNUTLS_X509_INT_OVERWRITE);
+}
+
+int
+_gnutls_x509_read_key_int_le(ASN1_TYPE node, const char *value,
+ bigint_t * ret_mpi)
+{
+ return __gnutls_x509_read_int(node, value, ret_mpi,
+ GNUTLS_X509_INT_OVERWRITE |
+ GNUTLS_X509_INT_LE);
}
/* Writes the specified integer into the specified node.
*/
static int
__gnutls_x509_write_int(ASN1_TYPE node, const char *value, bigint_t mpi,
- int lz, int overwrite)
+ unsigned int flags)
{
uint8_t *tmpstr;
size_t s_len;
int result;
s_len = 0;
- if (lz)
+ if (flags & GNUTLS_X509_INT_LZ)
result = _gnutls_mpi_print_lz(mpi, NULL, &s_len);
+ else if (GNUTLS_X509_INT_LE)
+ result = _gnutls_mpi_print_le(mpi, NULL, &s_len);
else
result = _gnutls_mpi_print(mpi, NULL, &s_len);
@@ -335,8 +380,10 @@ __gnutls_x509_write_int(ASN1_TYPE node, const char *value, bigint_t mpi,
return GNUTLS_E_MEMORY_ERROR;
}
- if (lz)
+ if (flags & GNUTLS_X509_INT_LZ)
result = _gnutls_mpi_print_lz(mpi, tmpstr, &s_len);
+ else if (GNUTLS_X509_INT_LE)
+ result = _gnutls_mpi_print_le(mpi, tmpstr, &s_len);
else
result = _gnutls_mpi_print(mpi, tmpstr, &s_len);
@@ -347,8 +394,8 @@ __gnutls_x509_write_int(ASN1_TYPE node, const char *value, bigint_t mpi,
}
result = asn1_write_value(node, value, tmpstr, s_len);
-
- if (overwrite)
+
+ if (flags & GNUTLS_X509_INT_OVERWRITE)
zeroize_key(tmpstr, s_len);
gnutls_free(tmpstr);
@@ -365,12 +412,23 @@ int
_gnutls_x509_write_int(ASN1_TYPE node, const char *value, bigint_t mpi,
int lz)
{
- return __gnutls_x509_write_int(node, value, mpi, lz, 0);
+ return __gnutls_x509_write_int(node, value, mpi,
+ lz ? GNUTLS_X509_INT_LZ : 0);
}
int
_gnutls_x509_write_key_int(ASN1_TYPE node, const char *value, bigint_t mpi,
int lz)
{
- return __gnutls_x509_write_int(node, value, mpi, lz, 1);
+ return __gnutls_x509_write_int(node, value, mpi,
+ (lz ? GNUTLS_X509_INT_LZ : 0) |
+ GNUTLS_X509_INT_OVERWRITE);
+}
+
+int
+_gnutls_x509_write_key_int_le(ASN1_TYPE node, const char *value, bigint_t mpi)
+{
+ return __gnutls_x509_write_int(node, value, mpi,
+ GNUTLS_X509_INT_OVERWRITE |
+ GNUTLS_X509_INT_LE);
}
diff --git a/lib/mpi.h b/lib/mpi.h
index af3e37b775..2715c2ddc1 100644
--- a/lib/mpi.h
+++ b/lib/mpi.h
@@ -57,8 +57,10 @@ bigint_t _gnutls_mpi_random_modp(bigint_t, bigint_t p,
#define _gnutls_prime_check _gnutls_mpi_ops.bigint_prime_check
#define _gnutls_mpi_print(x,y,z) _gnutls_mpi_ops.bigint_print(x,y,z,GNUTLS_MPI_FORMAT_USG)
#define _gnutls_mpi_print_lz(x,y,z) _gnutls_mpi_ops.bigint_print(x,y,z,GNUTLS_MPI_FORMAT_STD)
+#define _gnutls_mpi_print_le(x,y,z) _gnutls_mpi_ops.bigint_print(x,y,z,GNUTLS_MPI_FORMAT_ULE)
#define _gnutls_mpi_copy _gnutls_mpi_ops.bigint_copy
#define _gnutls_mpi_scan(r, b, s) _gnutls_mpi_ops.bigint_scan(r, b, s, GNUTLS_MPI_FORMAT_USG)
+#define _gnutls_mpi_scan_le(r, b, s) _gnutls_mpi_ops.bigint_scan(r, b, s, GNUTLS_MPI_FORMAT_ULE)
inline static
void _gnutls_mpi_release(bigint_t * x)
@@ -74,6 +76,8 @@ int _gnutls_mpi_init_scan(bigint_t * ret_mpi, const void *buffer,
size_t nbytes);
int _gnutls_mpi_init_scan_nz(bigint_t * ret_mpi, const void *buffer,
size_t nbytes);
+int _gnutls_mpi_init_scan_le(bigint_t * ret_mpi, const void *buffer,
+ size_t nbytes);
int _gnutls_mpi_dprint_lz(const bigint_t a, gnutls_datum_t * dest);
int _gnutls_mpi_dprint(const bigint_t a, gnutls_datum_t * dest);
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index 77f673f656..8f8733b358 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -379,6 +379,11 @@ int _gnutls_x509_read_key_int(ASN1_TYPE node, const char *value,
int _gnutls_x509_write_key_int(ASN1_TYPE node, const char *value, bigint_t mpi,
int lz);
+int _gnutls_x509_read_key_int_le(ASN1_TYPE node, const char *value,
+ bigint_t * ret_mpi);
+int _gnutls_x509_write_key_int_le(ASN1_TYPE node, const char *value,
+ bigint_t mpi);
+
int _gnutls_x509_read_pkalgo_params(ASN1_TYPE src, const char *src_name,
gnutls_x509_spki_st *params, unsigned is_sig);
int _gnutls_x509_write_sign_params(ASN1_TYPE dst, const char *dst_name,