const char * _gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits) { const char *result = NULL; gcry_pk_spec_t *spec; gcry_sexp_t keyparms = NULL; if (r_nbits) *r_nbits = 0; if (key) { iterator = 0; if (spec_from_sexp (key, 0, &spec, &keyparms)) return NULL; } else { spec = spec_from_name ("ecc"); if (!spec) return NULL; } if (spec->get_curve) result = spec->get_curve (keyparms, iterator, r_nbits); sexp_release (keyparms); return result; }
/* Get the number of nbits from the public key. Hmmm: Should we have really this function or is it better to have a more general function to retrieve different properties of the key? */ unsigned int _gcry_pk_get_nbits (gcry_sexp_t key) { gcry_pk_spec_t *spec; gcry_sexp_t parms; unsigned int nbits; /* Parsing KEY might be considered too much overhead. For example for RSA we would only need to look at P and stop parsing right away. However, with ECC things are more complicate in that only a curve name might be specified. Thus we need to tear the sexp apart. */ if (spec_from_sexp (key, 0, &spec, &parms)) return 0; /* Error - 0 is a suitable indication for that. */ nbits = spec->get_nbits (parms); sexp_release (parms); return nbits; }
/* Test a key. This may be used either for a public or a secret key to see whether the internal structure is okay. Returns: 0 or an errorcode. NOTE: We currently support only secret key checking. */ gcry_err_code_t _gcry_pk_testkey (gcry_sexp_t s_key) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; rc = spec_from_sexp (s_key, 1, &spec, &keyparms); if (rc) goto leave; if (spec->check_secret_key) rc = spec->check_secret_key (keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; }
/* Verify a signature. Caller has to supply the public key pkey, the signature sig and his hashvalue data. Public key has to be a standard public key given as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data must be an S-Exp like the one in sign too. */ gcry_err_code_t _gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms); if (rc) goto leave; if (spec->verify) rc = spec->verify (s_sig, s_hash, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; }
/* Create a signature. Caller has to provide a secret key as the SEXP skey and data expressed as a SEXP list hash with only one element which should instantly be available as a MPI. Alternatively the structure given below may be used for S_HASH, it provides the abiliy to pass flags to the operation; the flags defined by now are "pkcs1" which does PKCS#1 block type 1 style padding and "pss" for PSS encoding. Returns: 0 or an errorcode. In case of 0 the function returns a new SEXP with the signature value; the structure of this signature depends on the other arguments but is always suitable to be passed to gcry_pk_verify s_hash = See comment for _gcry-pk_util_data_to_mpi s_skey = <key-as-defined-in-sexp_to_key> r_sig = (sig-val (<algo> (<param_name1> <mpi>) ... (<param_namen> <mpi>)) [(hash algo)]) Note that (hash algo) in R_SIG is not used. */ gcry_err_code_t _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; *r_sig = NULL; rc = spec_from_sexp (s_skey, 1, &spec, &keyparms); if (rc) goto leave; if (spec->sign) rc = spec->sign (r_sig, s_hash, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; }
/* Do a PK decrypt operation Caller has to provide a secret key as the SEXP skey and data in a format as created by gcry_pk_encrypt. For historic reasons the function returns simply an MPI as an S-expression part; this is deprecated and the new method should be used which returns a real S-expressionl this is selected by adding at least an empty flags list to S_DATA. Returns: 0 or an errorcode. s_data = (enc-val [(flags [raw, pkcs1, oaep])] (<algo> (<param_name1> <mpi>) ... (<param_namen> <mpi>) )) s_skey = <key-as-defined-in-sexp_to_key> r_plain= Either an incomplete S-expression without the parentheses or if the flags list is used (even if empty) a real S-expression: (value PLAIN). In raw mode (or no flags given) the returned value is to be interpreted as a signed MPI, thus it may have an extra leading zero octet even if not included in the original data. With pkcs1 or oaep decoding enabled the returned value is a verbatim octet string. */ gcry_err_code_t _gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; *r_plain = NULL; rc = spec_from_sexp (s_skey, 1, &spec, &keyparms); if (rc) goto leave; if (spec->decrypt) rc = spec->decrypt (r_plain, s_data, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; }
/* Do a PK encrypt operation Caller has to provide a public key as the SEXP pkey and data as a SEXP with just one MPI in it. Alternatively S_DATA might be a complex S-Expression, similar to the one used for signature verification. This provides a flag which allows to handle PKCS#1 block type 2 padding. The function returns a sexp which may be passed to to pk_decrypt. Returns: 0 or an errorcode. s_data = See comment for _gcry_pk_util_data_to_mpi s_pkey = <key-as-defined-in-sexp_to_key> r_ciph = (enc-val (<algo> (<param_name1> <mpi>) ... (<param_namen> <mpi>) )) */ gcry_error_t gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; *r_ciph = NULL; rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms); if (rc) goto leave; if (spec->encrypt) rc = spec->encrypt (r_ciph, s_data, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: gcry_sexp_release (keyparms); return gcry_error (rc); }