Changeset View
Changeset View
Standalone View
Standalone View
g10/pkglue.c
Context not available. | |||||
{ | { | ||||
gcry_sexp_t s_sig, s_hash, s_pkey; | gcry_sexp_t s_sig, s_hash, s_pkey; | ||||
int rc; | int rc; | ||||
unsigned int neededfixedlen = 0; | |||||
/* Make a sexp from pkey. */ | /* Make a sexp from pkey. */ | ||||
if (pkalgo == PUBKEY_ALGO_DSA) | if (pkalgo == PUBKEY_ALGO_DSA) | ||||
Context not available. | |||||
rc = gpg_error_from_syserror (); | rc = gpg_error_from_syserror (); | ||||
else | else | ||||
{ | { | ||||
rc = gcry_sexp_build (&s_pkey, NULL, | const char *fmt; | ||||
"(public-key(ecc(curve %s)" | |||||
"(flags eddsa)(q%m)))", | if (openpgp_oid_is_ed25519 (pkey[0])) | ||||
curve, pkey[1]); | fmt = "(public-key(ecc(curve %s)(flags eddsa)(q%m)))"; | ||||
else | |||||
fmt = "(public-key(ecc(curve %s)(q%m)))"; | |||||
rc = gcry_sexp_build (&s_pkey, NULL, fmt, curve, pkey[1]); | |||||
xfree (curve); | xfree (curve); | ||||
} | } | ||||
if (openpgp_oid_is_ed25519 (pkey[0])) | |||||
neededfixedlen = 256 / 8; | |||||
} | } | ||||
else | else | ||||
return GPG_ERR_PUBKEY_ALGO; | return GPG_ERR_PUBKEY_ALGO; | ||||
Context not available. | |||||
/* Put hash into a S-Exp s_hash. */ | /* Put hash into a S-Exp s_hash. */ | ||||
if (pkalgo == PUBKEY_ALGO_EDDSA) | if (pkalgo == PUBKEY_ALGO_EDDSA) | ||||
{ | { | ||||
if (gcry_sexp_build (&s_hash, NULL, | const char *fmt; | ||||
"(data(flags eddsa)(hash-algo sha512)(value %m))", | |||||
hash)) | if (openpgp_oid_is_ed25519 (pkey[0])) | ||||
fmt = "(data(flags eddsa)(hash-algo sha512)(value %m))"; | |||||
else | |||||
fmt = "(data(value %m))"; | |||||
if (gcry_sexp_build (&s_hash, NULL, fmt, hash)) | |||||
BUG (); /* gcry_sexp_build should never fail. */ | BUG (); /* gcry_sexp_build should never fail. */ | ||||
} | } | ||||
else | else | ||||
Context not available. | |||||
{ | { | ||||
gcry_mpi_t r = data[0]; | gcry_mpi_t r = data[0]; | ||||
gcry_mpi_t s = data[1]; | gcry_mpi_t s = data[1]; | ||||
size_t rlen, slen, n; /* (bytes) */ | |||||
char buf[64]; | |||||
unsigned int nbits; | |||||
log_assert (neededfixedlen <= sizeof buf); | |||||
if (!r || !s) | if (openpgp_oid_is_ed25519 (pkey[0])) | ||||
rc = gpg_error (GPG_ERR_BAD_MPI); | |||||
else if ((rlen = (gcry_mpi_get_nbits (r)+7)/8) > neededfixedlen || !rlen) | |||||
rc = gpg_error (GPG_ERR_BAD_MPI); | |||||
else if ((slen = (gcry_mpi_get_nbits (s)+7)/8) > neededfixedlen || !slen) | |||||
rc = gpg_error (GPG_ERR_BAD_MPI); | |||||
else | |||||
{ | { | ||||
/* We need to fixup the length in case of leading zeroes. | size_t rlen, slen, n; /* (bytes) */ | ||||
* OpenPGP does not allow leading zeroes and the parser for | char buf[64]; | ||||
* the signature packet has no information on the use curve, | unsigned int nbits; | ||||
* thus we need to do it here. We won't do it for opaque | unsigned int neededfixedlen = 256 / 8; | ||||
* MPIs under the assumption that they are known to be fine; | |||||
* we won't see them here anyway but the check is anyway | |||||
* required. Fixme: A nifty feature for gcry_sexp_build | |||||
* would be a format to left pad the value (e.g. "%*M"). */ | |||||
rc = 0; | |||||
if (rlen < neededfixedlen | |||||
&& !gcry_mpi_get_flag (r, GCRYMPI_FLAG_OPAQUE) | |||||
&& !(rc=gcry_mpi_print (GCRYMPI_FMT_USG, buf, sizeof buf, &n, r))) | |||||
{ | |||||
log_assert (n < neededfixedlen); | |||||
memmove (buf + (neededfixedlen - n), buf, n); | |||||
memset (buf, 0, neededfixedlen - n); | |||||
r = gcry_mpi_set_opaque_copy (NULL, buf, neededfixedlen * 8); | |||||
} | |||||
else if (rlen < neededfixedlen | |||||
&& gcry_mpi_get_flag (r, GCRYMPI_FLAG_OPAQUE)) | |||||
{ | |||||
const unsigned char *p; | |||||
p = gcry_mpi_get_opaque (r, &nbits); | log_assert (neededfixedlen <= sizeof buf); | ||||
n = (nbits+7)/8; | |||||
memcpy (buf + (neededfixedlen - n), p, n); | |||||
memset (buf, 0, neededfixedlen - n); | |||||
gcry_mpi_set_opaque_copy (r, buf, neededfixedlen * 8); | |||||
} | |||||
if (slen < neededfixedlen | |||||
&& !gcry_mpi_get_flag (s, GCRYMPI_FLAG_OPAQUE) | |||||
&& !(rc=gcry_mpi_print (GCRYMPI_FMT_USG, buf, sizeof buf, &n, s))) | |||||
{ | |||||
log_assert (n < neededfixedlen); | |||||
memmove (buf + (neededfixedlen - n), buf, n); | |||||
memset (buf, 0, neededfixedlen - n); | |||||
s = gcry_mpi_set_opaque_copy (NULL, buf, neededfixedlen * 8); | |||||
} | |||||
else if (slen < neededfixedlen | |||||
&& gcry_mpi_get_flag (s, GCRYMPI_FLAG_OPAQUE)) | |||||
{ | |||||
const unsigned char *p; | |||||
p = gcry_mpi_get_opaque (s, &nbits); | if (!r || !s) | ||||
n = (nbits+7)/8; | rc = gpg_error (GPG_ERR_BAD_MPI); | ||||
memcpy (buf + (neededfixedlen - n), p, n); | else if ((rlen = (gcry_mpi_get_nbits (r)+7)/8) > neededfixedlen || !rlen) | ||||
memset (buf, 0, neededfixedlen - n); | rc = gpg_error (GPG_ERR_BAD_MPI); | ||||
gcry_mpi_set_opaque_copy (s, buf, neededfixedlen * 8); | else if ((slen = (gcry_mpi_get_nbits (s)+7)/8) > neededfixedlen || !slen) | ||||
rc = gpg_error (GPG_ERR_BAD_MPI); | |||||
else | |||||
{ | |||||
/* We need to fixup the length in case of leading zeroes. | |||||
* OpenPGP does not allow leading zeroes and the parser for | |||||
* the signature packet has no information on the use curve, | |||||
* thus we need to do it here. We won't do it for opaque | |||||
* MPIs under the assumption that they are known to be fine; | |||||
* we won't see them here anyway but the check is anyway | |||||
* required. Fixme: A nifty feature for gcry_sexp_build | |||||
* would be a format to left pad the value (e.g. "%*M"). */ | |||||
rc = 0; | |||||
if (rlen < neededfixedlen | |||||
&& !gcry_mpi_get_flag (r, GCRYMPI_FLAG_OPAQUE) | |||||
&& !(rc=gcry_mpi_print (GCRYMPI_FMT_USG, buf, sizeof buf, &n, r))) | |||||
{ | |||||
log_assert (n < neededfixedlen); | |||||
memmove (buf + (neededfixedlen - n), buf, n); | |||||
memset (buf, 0, neededfixedlen - n); | |||||
r = gcry_mpi_set_opaque_copy (NULL, buf, neededfixedlen * 8); | |||||
} | |||||
else if (rlen < neededfixedlen | |||||
&& gcry_mpi_get_flag (r, GCRYMPI_FLAG_OPAQUE)) | |||||
{ | |||||
const unsigned char *p; | |||||
p = gcry_mpi_get_opaque (r, &nbits); | |||||
n = (nbits+7)/8; | |||||
memcpy (buf + (neededfixedlen - n), p, n); | |||||
memset (buf, 0, neededfixedlen - n); | |||||
gcry_mpi_set_opaque_copy (r, buf, neededfixedlen * 8); | |||||
} | |||||
if (slen < neededfixedlen | |||||
&& !gcry_mpi_get_flag (s, GCRYMPI_FLAG_OPAQUE) | |||||
&& !(rc=gcry_mpi_print (GCRYMPI_FMT_USG, buf, sizeof buf, &n, s))) | |||||
{ | |||||
log_assert (n < neededfixedlen); | |||||
memmove (buf + (neededfixedlen - n), buf, n); | |||||
memset (buf, 0, neededfixedlen - n); | |||||
s = gcry_mpi_set_opaque_copy (NULL, buf, neededfixedlen * 8); | |||||
} | |||||
else if (slen < neededfixedlen | |||||
&& gcry_mpi_get_flag (s, GCRYMPI_FLAG_OPAQUE)) | |||||
{ | |||||
const unsigned char *p; | |||||
p = gcry_mpi_get_opaque (s, &nbits); | |||||
n = (nbits+7)/8; | |||||
memcpy (buf + (neededfixedlen - n), p, n); | |||||
memset (buf, 0, neededfixedlen - n); | |||||
gcry_mpi_set_opaque_copy (s, buf, neededfixedlen * 8); | |||||
} | |||||
} | } | ||||
} | |||||
else | |||||
rc = 0; | |||||
if (!rc) | if (!rc) | ||||
rc = gcry_sexp_build (&s_sig, NULL, | rc = gcry_sexp_build (&s_sig, NULL, | ||||
"(sig-val(eddsa(r%M)(s%M)))", r, s); | "(sig-val(eddsa(r%M)(s%M)))", r, s); | ||||
if (r != data[0]) | if (r != data[0]) | ||||
gcry_mpi_release (r); | gcry_mpi_release (r); | ||||
if (s != data[1]) | if (s != data[1]) | ||||
gcry_mpi_release (s); | gcry_mpi_release (s); | ||||
} | |||||
} | } | ||||
else if (pkalgo == PUBKEY_ALGO_ELGAMAL || pkalgo == PUBKEY_ALGO_ELGAMAL_E) | else if (pkalgo == PUBKEY_ALGO_ELGAMAL || pkalgo == PUBKEY_ALGO_ELGAMAL_E) | ||||
{ | { | ||||
Context not available. | |||||
rc = gpg_error_from_syserror (); | rc = gpg_error_from_syserror (); | ||||
else | else | ||||
{ | { | ||||
rc = gcry_sexp_build (&s_skey, NULL, | const char *fmt; | ||||
"(private-key(ecc(curve %s)" | |||||
"(flags eddsa)(q%m)(d%m)))", | if (openpgp_oid_is_ed25519 (skey[0])) | ||||
curve, skey[1], skey[2]); | fmt = "(private-key(ecc(curve %s)(flags eddsa)(q%m)(d%m)))"; | ||||
else | |||||
fmt = "(private-key(ecc(curve %s)(q%m)(d%m)))"; | |||||
rc = gcry_sexp_build (&s_skey, NULL, fmt, curve, skey[1], skey[2]); | |||||
xfree (curve); | xfree (curve); | ||||
} | } | ||||
} | } | ||||
Context not available. |