From 5025ed9dc3ba8a0f08097457748dd9f302a6d316 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Tue, 12 Dec 2023 10:19:52 +0000 Subject: [PATCH] secp256k1 extmod: minor cleanups, add private key check --- extmod/secp256k1mod.c | 50 ++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/extmod/secp256k1mod.c b/extmod/secp256k1mod.c index 31498015..aead92fb 100755 --- a/extmod/secp256k1mod.c +++ b/extmod/secp256k1mod.c @@ -20,40 +20,56 @@ #include #include +int privkey_check( + const secp256k1_context * ctx, + const unsigned char * privkey_bytes, + const Py_ssize_t privkey_bytes_len, + const char * desc + ) { + if (privkey_bytes_len != 32) { + char buf[64 + strlen(desc)]; + sprintf(buf, "%s length not 32 bytes", desc); + PyErr_SetString(PyExc_ValueError, buf); + return 0; + } + if (secp256k1_ec_seckey_verify(ctx, privkey_bytes) != 1) { + char buf[64 + strlen(desc)]; + sprintf(buf, "%s not in allowable range", desc); + PyErr_SetString(PyExc_ValueError, buf); + return 0; + } + return 1; +} + static PyObject * pubkey_gen(PyObject *self, PyObject *args) { - const unsigned char * privkey; - const int klen; + const unsigned char * privkey_bytes; + const Py_ssize_t privkey_bytes_len; const int compressed; - if (!PyArg_ParseTuple(args, "y#I", &privkey, &klen, &compressed)) { + if (!PyArg_ParseTuple(args, "y#I", &privkey_bytes, &privkey_bytes_len, &compressed)) { PyErr_SetString(PyExc_ValueError, "Unable to parse extension mod arguments"); return NULL; } - if (klen != 32) { - PyErr_SetString(PyExc_ValueError, "Private key length not 32 bytes"); - return NULL; - } + size_t pubkey_bytes_len = compressed == 1 ? 33 : 65; + unsigned char pubkey_bytes[pubkey_bytes_len]; secp256k1_pubkey pubkey; - size_t pubkeyclen = compressed == 1 ? 33 : 65; - unsigned char pubkeyc[pubkeyclen]; - static secp256k1_context *ctx = NULL; - if (ctx == NULL) { - /* puts ("Initializing context"); */ - ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - } + secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); if (ctx == NULL) { PyErr_SetString(PyExc_RuntimeError, "Context initialization failed"); return NULL; } - if (secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) != 1) { + if (!privkey_check(ctx, privkey_bytes, privkey_bytes_len, "Private key")) { + return NULL; + } + if (secp256k1_ec_pubkey_create(ctx, &pubkey, privkey_bytes) != 1) { PyErr_SetString(PyExc_RuntimeError, "Public key creation failed"); return NULL; } - if (secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, + if (secp256k1_ec_pubkey_serialize(ctx, pubkey_bytes, &pubkey_bytes_len, &pubkey, compressed == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED) != 1) { PyErr_SetString(PyExc_RuntimeError, "Public key serialization failed"); return NULL; } - return Py_BuildValue("y#", pubkeyc,pubkeyclen); + return Py_BuildValue("y#", pubkey_bytes, pubkey_bytes_len); } /* https://docs.python.org/3/howto/cporting.html */