diff --git a/src/math/gmp_desc.c b/src/math/gmp_desc.c index 403211b..b09aab3 100644 --- a/src/math/gmp_desc.c +++ b/src/math/gmp_desc.c @@ -138,13 +138,49 @@ static int twoexpt(void *a, int n) /* ---- conversions ---- */ +static const char rmap[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; + /* read ascii string */ static int read_radix(void *a, const char *b, int radix) { + int ret; LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); - mpz_set_str(a, b, radix); - return CRYPT_OK; + if (radix == 64) { + /* Sadly, GMP only supports radixes up to 62, but we need 64. + * So, although this is not the most elegant or efficient way, + * let's just convert the base 64 string (6 bits per digit) to + * an octal string (3 bits per digit) that's twice as long. */ + char c, *tmp, *q; + const char *p; + int i; + tmp = XMALLOC (1 + 2 * strlen (b)); + if (tmp == NULL) { + return CRYPT_MEM; + } + p = b; + q = tmp; + while ((c = *p++) != 0) { + for (i = 0; i < 64; i++) { + if (c == rmap[i]) + break; + } + if (i == 64) { + XFREE (tmp); + // printf ("c = '%c'\n", c); + return CRYPT_ERROR; + } + *q++ = '0' + (i / 8); + *q++ = '0' + (i % 8); + } + *q = 0; + ret = mpz_set_str(a, tmp, 8); + // printf ("ret = %d for '%s'\n", ret, tmp); + XFREE (tmp); + } else { + ret = mpz_set_str(a, b, radix); + } + return (ret == 0 ? CRYPT_OK : CRYPT_ERROR); } /* write one */