diff options
author | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2016-11-29 05:28:17 +0300 |
---|---|---|
committer | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2018-06-23 12:20:15 +0300 |
commit | c77aa89206d633aa8218e245babb98ac195281e2 (patch) | |
tree | 4be34034bb21e5e108d07af0647929f250082364 | |
parent | 05cd755fa46b0dfaa7aab9aa64627e41129fb7f7 (diff) | |
download | gnutls-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.h | 4 | ||||
-rw-r--r-- | lib/mpi.c | 82 | ||||
-rw-r--r-- | lib/mpi.h | 4 | ||||
-rw-r--r-- | lib/x509/x509_int.h | 5 |
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 */ @@ -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); } @@ -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, |