summaryrefslogtreecommitdiff
path: root/lib/mpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mpi.c')
-rw-r--r--lib/mpi.c107
1 files changed, 95 insertions, 12 deletions
diff --git a/lib/mpi.c b/lib/mpi.c
index afe1c0ea7d..083afe0fa7 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,43 @@ _gnutls_mpi_dprint_size(const bigint_t a, gnutls_datum_t * dest,
return 0;
}
+/* like _gnutls_mpi_dprint_size, but prints into preallocated byte buffer */
+int
+_gnutls_mpi_bprint_size(const bigint_t a, uint8_t *buf, size_t size)
+{
+ int result;
+ size_t bytes = 0;
+
+ result = _gnutls_mpi_print(a, NULL, &bytes);
+ if (result != GNUTLS_E_SHORT_MEMORY_BUFFER)
+ return gnutls_assert_val(result);
+
+ if (bytes <= size) {
+ unsigned i;
+ size_t diff = size - bytes;
+
+ for (i = 0; i < diff; i++)
+ buf[i] = 0;
+ result = _gnutls_mpi_print(a, &buf[diff], &bytes);
+ } else {
+ result = _gnutls_mpi_print(a, buf, &bytes);
+ }
+
+ return result;
+}
+
+/* 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 +332,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 +355,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 +405,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 +419,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 +437,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);
}