Skip to content

Commit

Permalink
Merge bitcoin-core/secp256k1#783: Make the public API docs more consi…
Browse files Browse the repository at this point in the history
…stent and explicit

adec5a1 Add missing null check for ctx and input keys in the public API (Elichai Turkel)
f4edfc7 Improve consistency for NULL arguments in the public interface (Elichai Turkel)

Pull request description:

  I went over the public API and added missing explanations on when a pointer can be null and when it cannot,
  and added some missing checks for null ctx and null pubkey pointers.

  Open questions IMHO:
  1. Can `secp256k1_context_create` return NULL? right now it could return null if you replaced the callbacks at compile time to ones that do return(unlike the default ones which never return).
  2. Related to the first, should we document that the callbacks should never return? (in the tests we use returning callbacks but we can violate our own API) right now we say the following:

  > After this callback returns, anything may happen, including crashing.

  Is this enough to document answer `no` for the first question and just saying that if the callback returned then you violated the API so `secp256k1_context_create` can return NULL even though it is promised not to?
  Right now we AFAICT we never check if it returns null

  Another nit I'm not sure about is wording `(does nothing if NULL)`/`(ignored if NULL)`/`(can be NULL)`

  More missing docs:
  1. Documenting the `data` argument to the default nonce functions

ACKs for top commit:
  ariard:
    ACK adec5a1
  jonasnick:
    ACK adec5a1

Tree-SHA512: 6fe785776b7e451e9e8cae944987f927b1eb2e2d404dfcb1b0ceb0a30bda4ce16469708920269417e5ada09739723a430e270dea1868fe7d12ccd5699dde5976
  • Loading branch information
real-or-random committed Sep 15, 2021
2 parents 9a5a87e + adec5a1 commit aa5d34a
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 134 deletions.
97 changes: 48 additions & 49 deletions include/secp256k1.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ SECP256K1_API secp256k1_context* secp256k1_context_create(
* memory allocation entirely, see the functions in secp256k1_preallocated.h.
*
* Returns: a newly created context object.
* Args: ctx: an existing context to copy (cannot be NULL)
* Args: ctx: an existing context to copy
*/
SECP256K1_API secp256k1_context* secp256k1_context_clone(
const secp256k1_context* ctx
Expand All @@ -247,7 +247,7 @@ SECP256K1_API secp256k1_context* secp256k1_context_clone(
*/
SECP256K1_API void secp256k1_context_destroy(
secp256k1_context* ctx
);
) SECP256K1_ARG_NONNULL(1);

/** Set a callback function to be called when an illegal argument is passed to
* an API call. It will only trigger for violations that are mentioned
Expand Down Expand Up @@ -278,11 +278,11 @@ SECP256K1_API void secp256k1_context_destroy(
* fails. In this case, the corresponding default handler will be called with
* the data pointer argument set to NULL.
*
* Args: ctx: an existing context object (cannot be NULL)
* Args: ctx: an existing context object.
* In: fun: a pointer to a function to call when an illegal argument is
* passed to the API, taking a message and an opaque pointer.
* (NULL restores the default handler.)
* data: the opaque pointer to pass to fun above.
* data: the opaque pointer to pass to fun above, must be NULL for the default handler.
*
* See also secp256k1_context_set_error_callback.
*/
Expand All @@ -302,12 +302,12 @@ SECP256K1_API void secp256k1_context_set_illegal_callback(
* for that). After this callback returns, anything may happen, including
* crashing.
*
* Args: ctx: an existing context object (cannot be NULL)
* Args: ctx: an existing context object.
* In: fun: a pointer to a function to call when an internal error occurs,
* taking a message and an opaque pointer (NULL restores the
* default handler, see secp256k1_context_set_illegal_callback
* for details).
* data: the opaque pointer to pass to fun above.
* data: the opaque pointer to pass to fun above, must be NULL for the default handler.
*
* See also secp256k1_context_set_illegal_callback.
*/
Expand All @@ -320,7 +320,7 @@ SECP256K1_API void secp256k1_context_set_error_callback(
/** Create a secp256k1 scratch space object.
*
* Returns: a newly created scratch space.
* Args: ctx: an existing context object (cannot be NULL)
* Args: ctx: an existing context object.
* In: size: amount of memory to be available as scratch space. Some extra
* (<100 bytes) will be allocated for extra accounting.
*/
Expand Down Expand Up @@ -480,16 +480,16 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
* Returns: 1: correct signature
* 0: incorrect or unparseable signature
* Args: ctx: a secp256k1 context object, initialized for verification.
* In: sig: the signature being verified (cannot be NULL)
* msghash32: the 32-byte message hash being verified (cannot be NULL).
* In: sig: the signature being verified.
* msghash32: the 32-byte message hash being verified.
* The verifier must make sure to apply a cryptographic
* hash function to the message by itself and not accept an
* msghash32 value directly. Otherwise, it would be easy to
* create a "valid" signature without knowledge of the
* secret key. See also
* https://bitcoin.stackexchange.com/a/81116/35586 for more
* background on this topic.
* pubkey: pointer to an initialized public key to verify with (cannot be NULL)
* pubkey: pointer to an initialized public key to verify with.
*
* To avoid accepting malleable signatures, only ECDSA signatures in lower-S
* form are accepted.
Expand All @@ -515,8 +515,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
* or copy if the input was already normalized. (can be NULL if
* you're only interested in whether the input was already
* normalized).
* In: sigin: a pointer to a signature to check/normalize (cannot be NULL,
* can be identical to sigout)
* In: sigin: a pointer to a signature to check/normalize (can be identical to sigout)
*
* With ECDSA a third-party can forge a second distinct signature of the same
* message, given a single initial signature, but without knowing the key. This
Expand Down Expand Up @@ -568,12 +567,16 @@ SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_def
*
* Returns: 1: signature created
* 0: the nonce generation function failed, or the secret key was invalid.
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
* In: msghash32: the 32-byte message hash being signed (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL)
* noncefp: pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
* Args: ctx: pointer to a context object, initialized for signing.
* Out: sig: pointer to an array where the signature will be placed.
* In: msghash32: the 32-byte message hash being signed.
* seckey: pointer to a 32-byte secret key.
* noncefp: pointer to a nonce generation function. If NULL,
* secp256k1_nonce_function_default is used.
* ndata: pointer to arbitrary data used by the nonce generation function
* (can be NULL). If it is non-NULL and
* secp256k1_nonce_function_default is used, then ndata must be a
* pointer to 32-bytes of additional data.
*
* The created signature is always in lower-S form. See
* secp256k1_ecdsa_signature_normalize for more details.
Expand All @@ -596,8 +599,8 @@ SECP256K1_API int secp256k1_ecdsa_sign(
*
* Returns: 1: secret key is valid
* 0: secret key is invalid
* Args: ctx: pointer to a context object (cannot be NULL)
* In: seckey: pointer to a 32-byte secret key (cannot be NULL)
* Args: ctx: pointer to a context object.
* In: seckey: pointer to a 32-byte secret key.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
const secp256k1_context* ctx,
Expand All @@ -606,11 +609,11 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(

/** Compute the public key for a secret key.
*
* Returns: 1: secret was valid, public key stores
* 0: secret was invalid, try again
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* Out: pubkey: pointer to the created public key (cannot be NULL)
* In: seckey: pointer to a 32-byte secret key (cannot be NULL)
* Returns: 1: secret was valid, public key stores.
* 0: secret was invalid, try again.
* Args: ctx: pointer to a context object, initialized for signing.
* Out: pubkey: pointer to the created public key.
* In: seckey: pointer to a 32-byte secret key.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
const secp256k1_context* ctx,
Expand All @@ -626,8 +629,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
* In/Out: seckey: pointer to the 32-byte secret key to be negated. If the
* secret key is invalid according to
* secp256k1_ec_seckey_verify, this function returns 0 and
* seckey will be set to some unspecified value. (cannot be
* NULL)
* seckey will be set to some unspecified value.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_negate(
const secp256k1_context* ctx,
Expand All @@ -645,7 +647,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate(
*
* Returns: 1 always
* Args: ctx: pointer to a context object
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL)
* In/Out: pubkey: pointer to the public key to be negated.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
const secp256k1_context* ctx,
Expand All @@ -657,15 +659,15 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
* Returns: 0 if the arguments are invalid or the resulting secret key would be
* invalid (only when the tweak is the negation of the secret key). 1
* otherwise.
* Args: ctx: pointer to a context object (cannot be NULL).
* Args: ctx: pointer to a context object.
* In/Out: seckey: pointer to a 32-byte secret key. If the secret key is
* invalid according to secp256k1_ec_seckey_verify, this
* function returns 0. seckey will be set to some unspecified
* value if this function returns 0. (cannot be NULL)
* value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
* secp256k1_ec_seckey_verify, this function returns 0. For
* uniformly random 32-byte arrays the chance of being invalid
* is negligible (around 1 in 2^128) (cannot be NULL).
* is negligible (around 1 in 2^128).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_add(
const secp256k1_context* ctx,
Expand All @@ -686,14 +688,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
* Returns: 0 if the arguments are invalid or the resulting public key would be
* invalid (only when the tweak is the negation of the corresponding
* secret key). 1 otherwise.
* Args: ctx: pointer to a context object initialized for validation
* (cannot be NULL).
* Args: ctx: pointer to a context object initialized for validation.
* In/Out: pubkey: pointer to a public key object. pubkey will be set to an
* invalid value if this function returns 0 (cannot be NULL).
* invalid value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
* secp256k1_ec_seckey_verify, this function returns 0. For
* uniformly random 32-byte arrays the chance of being invalid
* is negligible (around 1 in 2^128) (cannot be NULL).
* is negligible (around 1 in 2^128).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
const secp256k1_context* ctx,
Expand All @@ -704,15 +705,15 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
/** Tweak a secret key by multiplying it by a tweak.
*
* Returns: 0 if the arguments are invalid. 1 otherwise.
* Args: ctx: pointer to a context object (cannot be NULL).
* Args: ctx: pointer to a context object.
* In/Out: seckey: pointer to a 32-byte secret key. If the secret key is
* invalid according to secp256k1_ec_seckey_verify, this
* function returns 0. seckey will be set to some unspecified
* value if this function returns 0. (cannot be NULL)
* value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
* secp256k1_ec_seckey_verify, this function returns 0. For
* uniformly random 32-byte arrays the chance of being invalid
* is negligible (around 1 in 2^128) (cannot be NULL).
* is negligible (around 1 in 2^128).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_mul(
const secp256k1_context* ctx,
Expand All @@ -731,14 +732,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
/** Tweak a public key by multiplying it by a tweak value.
*
* Returns: 0 if the arguments are invalid. 1 otherwise.
* Args: ctx: pointer to a context object initialized for validation
* (cannot be NULL).
* Args: ctx: pointer to a context object initialized for validation.
* In/Out: pubkey: pointer to a public key object. pubkey will be set to an
* invalid value if this function returns 0 (cannot be NULL).
* invalid value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
* secp256k1_ec_seckey_verify, this function returns 0. For
* uniformly random 32-byte arrays the chance of being invalid
* is negligible (around 1 in 2^128) (cannot be NULL).
* is negligible (around 1 in 2^128).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
const secp256k1_context* ctx,
Expand All @@ -749,7 +749,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
/** Updates the context randomization to protect against side-channel leakage.
* Returns: 1: randomization successfully updated or nothing to randomize
* 0: error
* Args: ctx: pointer to a context object (cannot be NULL)
* Args: ctx: pointer to a context object.
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state)
*
* While secp256k1 code is written to be constant-time no matter what secret
Expand Down Expand Up @@ -780,18 +780,17 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
*
* Returns: 1: the sum of the public keys is valid.
* 0: the sum of the public keys is not valid.
* Args: ctx: pointer to a context object
* Out: out: pointer to a public key object for placing the resulting public key
* (cannot be NULL)
* In: ins: pointer to array of pointers to public keys (cannot be NULL)
* n: the number of public keys to add together (must be at least 1)
* Args: ctx: pointer to a context object.
* Out: out: pointer to a public key object for placing the resulting public key.
* In: ins: pointer to array of pointers to public keys.
* n: the number of public keys to add together (must be at least 1).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine(
const secp256k1_context* ctx,
secp256k1_pubkey *out,
const secp256k1_pubkey * const * ins,
size_t n
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Compute a tagged hash as defined in BIP-340.
*
Expand Down
15 changes: 8 additions & 7 deletions include/secp256k1_ecdh.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,15 @@ SECP256K1_API extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_func
*
* Returns: 1: exponentiation was successful
* 0: scalar was invalid (zero or overflow) or hashfp returned 0
* Args: ctx: pointer to a context object (cannot be NULL)
* Out: output: pointer to an array to be filled by hashfp
* In: pubkey: a pointer to a secp256k1_pubkey containing an
* initialized public key
* seckey: a 32-byte scalar with which to multiply the point
* hashfp: pointer to a hash function. If NULL, secp256k1_ecdh_hash_function_sha256 is used
* (in which case, 32 bytes will be written to output)
* Args: ctx: pointer to a context object.
* Out: output: pointer to an array to be filled by hashfp.
* In: pubkey: a pointer to a secp256k1_pubkey containing an initialized public key.
* seckey: a 32-byte scalar with which to multiply the point.
* hashfp: pointer to a hash function. If NULL,
* secp256k1_ecdh_hash_function_sha256 is used
* (in which case, 32 bytes will be written to output).
* data: arbitrary data pointer that is passed through to hashfp
* (can be NULL for secp256k1_ecdh_hash_function_sha256).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
const secp256k1_context* ctx,
Expand Down
Loading

0 comments on commit aa5d34a

Please sign in to comment.