/* Turn VALUE into an octet string and store it in an allocated buffer at R_FRAME. If the resulting octet string is shorter than NBYTES the result will be left padded with zeroes. If VALUE does not fit into NBYTES an error code is returned. */ static gpg_err_code_t int2octets (unsigned char **r_frame, gcry_mpi_t value, size_t nbytes) { gpg_err_code_t rc; size_t nframe, noff, n; unsigned char *frame; rc = _gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nframe, value); if (rc) return rc; if (nframe > nbytes) return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES. */ noff = (nframe < nbytes)? nbytes - nframe : 0; n = nframe + noff; frame = mpi_is_secure (value)? xtrymalloc_secure (n) : xtrymalloc (n); if (!frame) return gpg_err_code_from_syserror (); if (noff) memset (frame, 0, noff); nframe += noff; rc = _gcry_mpi_print (GCRYMPI_FMT_USG, frame+noff, nframe-noff, NULL, value); if (rc) { xfree (frame); return rc; } *r_frame = frame; return 0; }
gcry_error_t gcry_mpi_print (enum gcry_mpi_format format, unsigned char *buffer, size_t buflen, size_t *nwritten, const gcry_mpi_t a) { return gpg_error (_gcry_mpi_print (format, buffer, buflen, nwritten, a)); }
gcry_mpi_t _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p) { gpg_err_code_t rc; int pbytes = (mpi_get_nbits (p)+7)/8; size_t n; unsigned char *buf, *ptr; gcry_mpi_t result; buf = xmalloc ( 1 + 2*pbytes ); *buf = 04; /* Uncompressed point. */ ptr = buf+1; rc = _gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x); if (rc) log_fatal ("mpi_print failed: %s\n", gpg_strerror (rc)); if (n < pbytes) { memmove (ptr+(pbytes-n), ptr, n); memset (ptr, 0, (pbytes-n)); } ptr += pbytes; rc = _gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y); if (rc) log_fatal ("mpi_print failed: %s\n", gpg_strerror (rc)); if (n < pbytes) { memmove (ptr+(pbytes-n), ptr, n); memset (ptr, 0, (pbytes-n)); } rc = _gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL); if (rc) log_fatal ("mpi_scan failed: %s\n", gpg_strerror (rc)); xfree (buf); return result; }
/* RESULT must have been initialized and is set on success to the point given by VALUE. */ gcry_err_code_t _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value) { gcry_err_code_t rc; size_t n; const unsigned char *buf; unsigned char *buf_memory; gcry_mpi_t x, y; if (mpi_is_opaque (value)) { unsigned int nbits; buf = mpi_get_opaque (value, &nbits); if (!buf) return GPG_ERR_INV_OBJ; n = (nbits + 7)/8; buf_memory = NULL; } else { n = (mpi_get_nbits (value)+7)/8; buf_memory = xmalloc (n); rc = _gcry_mpi_print (GCRYMPI_FMT_USG, buf_memory, n, &n, value); if (rc) { xfree (buf_memory); return rc; } buf = buf_memory; } if (n < 1) { xfree (buf_memory); return GPG_ERR_INV_OBJ; } if (*buf != 4) { xfree (buf_memory); return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression. */ } if ( ((n-1)%2) ) { xfree (buf_memory); return GPG_ERR_INV_OBJ; } n = (n-1)/2; rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL); if (rc) { xfree (buf_memory); return rc; } rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL); xfree (buf_memory); if (rc) { mpi_free (x); return rc; } mpi_set (result->x, x); mpi_set (result->y, y); mpi_set_ui (result->z, 1); mpi_free (x); mpi_free (y); return 0; }