packages feed

secp256k1 0.4.0 → 0.4.1

raw patch · 17 files changed

+612/−425 lines, 17 files

Files

Makefile.am view
@@ -41,6 +41,7 @@ noinst_HEADERS += src/field_impl.h noinst_HEADERS += src/bench.h noinst_HEADERS += contrib/lax_der_parsing.h+noinst_HEADERS += contrib/lax_der_privatekey_parsing.h  pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libsecp256k1.pc
haskell/src/Crypto/Secp256k1.hs view
@@ -2,14 +2,12 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-| Module      : Crypto.Secp256k1-Description : ECDSA on curve secp256k1-License     : PublicDomain-Maintainer  : root@haskoin.com+License     : MIT+Maintainer  : Jean-Pierre Rupp <root@haskoin.com> Stability   : experimental Portability : POSIX -This module exposes crytpographic functions from Bitcoin’s secp256k1 library.-Depends on <https://github.com/bitcoin/secp256k1 secp256k1>.+Crytpographic functions from Bitcoin’s secp256k1 library. -} module Crypto.Secp256k1     ( -- * Messages@@ -22,9 +20,6 @@     , secKey     , getSecKey     , derivePubKey-    -- ** BER-    , importSecKey-    , exportSecKey      -- * Public Keys     , PubKey@@ -69,19 +64,10 @@ import           Test.QuickCheck import           Text.Read --- | Internal public key data type. newtype PubKey = PubKey (ForeignPtr PubKey64)---- | Internal message data type. newtype Msg = Msg (ForeignPtr Msg32)---- | Internal signature data type. newtype Sig = Sig (ForeignPtr Sig64)---- | Internal secret key data type. newtype SecKey = SecKey (ForeignPtr SecKey32)---- | Internal tweak data type for addition and multiplication. newtype Tweak = Tweak (ForeignPtr Tweak32)  decodeHex :: ConvertibleStrings a ByteString => a -> Maybe ByteString@@ -168,7 +154,7 @@ instance Eq Tweak where     ft1 == ft2 = getTweak ft1 == getTweak ft2 --- | Create internal message data from 32-byte 'ByteString'.+-- | Import 32-byte 'ByteString' as 'Msg'. msg :: ByteString -> Maybe Msg msg bs     | BS.length bs == 32 = unsafePerformIO $ do@@ -177,7 +163,7 @@         return $ Just $ Msg fp     | otherwise = Nothing --- | Create internal secret key data from 32-byte 'ByteString'.+-- | Import 32-byte 'ByteString' as 'SecKey'. secKey :: ByteString -> Maybe SecKey secKey bs     | BS.length bs == 32 = unsafePerformIO $ do@@ -191,8 +177,8 @@     | otherwise = Nothing  -- | Convert signature to a normalized lower-S form. Boolean value 'True'--- indicates that the signature was normalized, 'False' indicates that it was--- already normal.+-- indicates that the signature changed, 'False' indicates that it was already+-- normal. normalizeSig :: Sig -> (Sig, Bool) normalizeSig (Sig fg) = unsafePerformIO $ do     fg' <- mallocForeignPtr@@ -200,7 +186,7 @@         ecdsaSignatureNormalize ctx pg' pg     return (Sig fg', isSuccess ret) --- | Create internal tweak data from 32-byte 'ByteString'.+-- | 32-Byte 'ByteString' as 'Tweak'. tweak :: ByteString -> Maybe Tweak tweak bs     | BS.length bs == 32 = unsafePerformIO $ do@@ -213,7 +199,7 @@ getSecKey :: SecKey -> ByteString getSecKey (SecKey fk) = getSecKey32 $ unsafePerformIO $ withForeignPtr fk peek --- | Get 64-byte internal public key representation.+-- Get 64-byte public key. getPubKey :: PubKey -> ByteString getPubKey (PubKey fp) = getPubKey64 $ unsafePerformIO $ withForeignPtr fp peek @@ -225,14 +211,14 @@ getTweak :: Tweak -> ByteString getTweak (Tweak ft) = getTweak32 $ unsafePerformIO $ withForeignPtr ft peek --- | Read DER-encoded public key.+-- | Import DER-encoded public key. importPubKey :: ByteString -> Maybe PubKey importPubKey bs = unsafePerformIO $ useByteString bs $ \(b, l) -> do     fp <- mallocForeignPtr     ret <- withForeignPtr fp $ \p -> ecPubKeyParse ctx p b l     if isSuccess ret then return $ Just $ PubKey fp else return Nothing --- | Encode public key as DER.  First argument 'True' for compressed output.+-- | Encode public key as DER. First argument 'True' for compressed output. exportPubKey :: Bool -> PubKey -> ByteString exportPubKey compress (PubKey pub) = unsafePerformIO $     withForeignPtr pub $ \p -> alloca $ \l -> allocaBytes z $ \o -> do@@ -245,7 +231,6 @@     c = if compress then compressed else uncompressed     z = if compress then 33 else 65 --- | Get compact signature. exportCompactSig :: Sig -> CompactSig exportCompactSig (Sig fg) = unsafePerformIO $     withForeignPtr fg $ \pg -> alloca $ \pc -> do@@ -253,7 +238,6 @@         unless (isSuccess ret) $ error "Could not obtain compact signature"         peek pc --- | Read compact signature. importCompactSig :: CompactSig -> Maybe Sig importCompactSig c = unsafePerformIO $ alloca $ \pc -> do     poke pc c@@ -261,7 +245,7 @@     ret <- withForeignPtr fg $ \pg -> ecdsaSignatureParseCompact ctx pg pc     if isSuccess ret then return $ Just $ Sig fg else return Nothing --- | Read DER-encoded signature.+-- | Import DER-encoded signature. importSig :: ByteString -> Maybe Sig importSig bs = unsafePerformIO $     useByteString bs $ \(b, l) -> do@@ -277,7 +261,7 @@         ret <- withForeignPtr fg $ \g -> laxDerParse ctx g b l         if isSuccess ret then return $ Just $ Sig fg else return Nothing --- | Encode signature as DER.+-- | Encode signature as strict DER. exportSig :: Sig -> ByteString exportSig (Sig fg) = unsafePerformIO $     withForeignPtr fg $ \g -> alloca $ \l -> allocaBytes 72 $ \o -> do@@ -293,7 +277,6 @@     withForeignPtr fp $ \p -> withForeignPtr fg $ \g ->         withForeignPtr fm $ \m -> isSuccess <$> ecdsaVerify ctx g m p --- | Sign message using secret key. signMsg :: SecKey -> Msg -> Sig signMsg (SecKey fk) (Msg fm) = unsafePerformIO $     withForeignPtr fk $ \k -> withForeignPtr fm $ \m -> do@@ -302,7 +285,6 @@         unless (isSuccess ret) $ error "could not sign message"         return $ Sig fg --- | Obtain public key from secret key. derivePubKey :: SecKey -> PubKey derivePubKey (SecKey fk) = unsafePerformIO $ withForeignPtr fk $ \k -> do     fp <- mallocForeignPtr@@ -310,27 +292,7 @@     unless (isSuccess ret) $ error "could not compute public key"     return $ PubKey fp --- | Read BER-encoded secret key.-importSecKey :: ByteString -> Maybe SecKey-importSecKey bs = unsafePerformIO $-    useByteString bs $ \(b, l) -> do-        fk <- mallocForeignPtr-        ret <- withForeignPtr fk $ \k -> ecSecKeyImport ctx k b l-        if isSuccess ret then return $ Just $ SecKey fk else return Nothing---- | Encode secret key as BER.  First argument 'True' for compressed output.-exportSecKey :: Bool -> SecKey -> ByteString-exportSecKey compress (SecKey fk) = unsafePerformIO $-    withForeignPtr fk $ \k -> alloca $ \l -> allocaBytes 279 $ \o -> do-        poke l 279-        ret <- ecSecKeyExport ctx o l k c-        unless (isSuccess ret) $ error "could not export secret key"-        n <- peek l-        packByteString (o, n)-  where-    c = if compress then compressed else uncompressed---- | Add tweak to secret key using ECDSA addition.+-- | Add tweak to secret key. tweakAddSecKey :: SecKey -> Tweak -> Maybe SecKey tweakAddSecKey (SecKey fk) (Tweak ft) = unsafePerformIO $     withForeignPtr fk $ \k -> withForeignPtr ft $ \t -> do@@ -341,7 +303,7 @@             ecSecKeyTweakAdd ctx k' t         if isSuccess ret then return $ Just $ SecKey fk' else return Nothing --- | Multiply secret key by tweak using ECDSA multiplication.+-- | Multiply secret key by tweak. tweakMulSecKey :: SecKey -> Tweak -> Maybe SecKey tweakMulSecKey (SecKey fk) (Tweak ft) = unsafePerformIO $     withForeignPtr fk $ \k -> withForeignPtr ft $ \t -> do@@ -352,8 +314,7 @@             ecSecKeyTweakMul ctx k' t         if isSuccess ret then return $ Just $ SecKey fk' else return Nothing --- | Perform ECDSA addition between the public key point and the point obtained--- by multiplying the tweak scalar by the curve generator.+-- | Add tweak to public key. Tweak is multiplied first by G to obtain a point. tweakAddPubKey :: PubKey -> Tweak -> Maybe PubKey tweakAddPubKey (PubKey fp) (Tweak ft) = unsafePerformIO $     withForeignPtr fp $ \p -> withForeignPtr ft $ \t -> do@@ -364,8 +325,8 @@             ecPubKeyTweakAdd ctx p' t         if isSuccess ret then return $ Just $ PubKey fp' else return Nothing --- | Perform ECDSA multiplication between the public key point and the point--- obtained by multiplying the tweak scalar by the curve generator.+-- | Multiply public key by tweak. Tweak is multiplied first by G to obtain a+-- point. tweakMulPubKey :: PubKey -> Tweak -> Maybe PubKey tweakMulPubKey (PubKey fp) (Tweak ft) = unsafePerformIO $     withForeignPtr fp $ \p -> withForeignPtr ft $ \t -> do@@ -376,7 +337,7 @@             ecPubKeyTweakMul ctx p' t         if isSuccess ret then return $ Just $ PubKey fp' else return Nothing --- | Add multiple public keys together using ECDSA addition.+-- | Add multiple public keys together. combinePubKeys :: [PubKey] -> Maybe PubKey combinePubKeys pubs = unsafePerformIO $ pointers [] pubs $ \ps ->     allocaArray (length ps) $ \a -> do
haskell/src/Crypto/Secp256k1/Internal.hs view
@@ -1,25 +1,23 @@ {-| Module      : Crypto.Secp256k1.Internal-Description : secp256k1 C bindings-License     : PublicDomain-Maintainer  : root@haskoin.com+License     : MIT+Maintainer  : Jean-Pierre Rupp <root@haskoin.com> Stability   : experimental Portability : POSIX -The API in this module may change at any time.  This is an internal module-only exposed for hacking and experimentation.+The API for this module may change at any time. This is an internal module only+exposed for hacking and experimentation. -} module Crypto.Secp256k1.Internal where  import           Control.Monad-import           Data.Binary            (Binary, get, put)-import           Data.Binary.Get        (runGet)-import           Data.Binary.Put        (runPut)-import           Data.ByteString        (ByteString, packCStringLen)-import           Data.ByteString.Lazy   (fromStrict, toStrict)-import           Data.ByteString.Unsafe (unsafePackCStringLen,-                                         unsafeUseAsCStringLen)-import           Data.LargeWord         (LargeKey (LargeKey), Word256)+import           Data.Binary          (Binary, get, put)+import           Data.Binary.Get      (runGet)+import           Data.Binary.Put      (runPut)+import           Data.ByteString      (ByteString, packCStringLen,+                                       useAsCStringLen)+import           Data.ByteString.Lazy (fromStrict, toStrict)+import           Data.LargeWord       (LargeKey (LargeKey), Word256) import           Foreign import           Foreign.C import           System.Entropy@@ -78,23 +76,23 @@     -> Ret  verify :: CtxFlags-verify = CtxFlags 1+verify = CtxFlags 0x0101  sign :: CtxFlags-sign = CtxFlags 2+sign = CtxFlags 0x0201  signVerify :: CtxFlags-signVerify = CtxFlags 3+signVerify = CtxFlags 0x0301  compressed :: SerFlags-compressed = SerFlags 1+compressed = SerFlags 0x0102  uncompressed :: SerFlags-uncompressed = SerFlags 0+uncompressed = SerFlags 0x0002  useByteString :: ByteString -> ((Ptr CUChar, CSize) -> IO a) -> IO a useByteString bs f =-    unsafeUseAsCStringLen bs $ \(b, l) -> f (castPtr b, fromIntegral l)+    useAsCStringLen bs $ \(b, l) -> f (castPtr b, fromIntegral l)  packByteString :: (Ptr CUChar, CSize) -> IO ByteString packByteString (b, l) = packCStringLen (castPtr b, fromIntegral l)@@ -116,7 +114,7 @@ instance Storable CompactSig where     sizeOf _ = 64     alignment _ = 1-    peek p = (runGet get . fromStrict) <$> unsafePackCStringLen (castPtr p, 64)+    peek p = (runGet get . fromStrict) <$> packCStringLen (castPtr p, 64)     poke p cs = useByteString bs $ \(b, _) -> copyArray (castPtr p) b 64 where         bs = toStrict $ runPut $ put cs @@ -319,25 +317,6 @@     :: Ptr Ctx     -> Ptr PubKey64     -> Ptr SecKey32-    -> IO Ret--foreign import ccall-    "secp256k1.h secp256k1_ec_privkey_export"-    ecSecKeyExport-    :: Ptr Ctx-    -> Ptr CUChar -- ^ array to store BER-encoded key (allocate 279 bytes)-    -> Ptr CSize -- ^ size of previous array, will be updated-    -> Ptr SecKey32-    -> SerFlags-    -> IO Ret--foreign import ccall-    "secp256k1.h secp256k1_ec_privkey_import"-    ecSecKeyImport-    :: Ptr Ctx-    -> Ptr SecKey32-    -> Ptr CUChar -- ^ BER-encoded private key-    -> CSize     -> IO Ret  foreign import ccall
haskell/test/Crypto/Secp256k1/Internal/Tests.hs view
@@ -39,8 +39,6 @@     , testGroup "Secret keys"         [ testCase "Verify secret key"        ecSecKeyVerifyTest         , testCase "Create public key"        ecPubkeyCreateTest-        , testCase "Serialize BER secret key" ecSecKeyExportTest-        , testCase "Import BER secret key"    ecSecKeyImportTest         , testCase "Tweak add secret key"     ecSecKeyTweakAddTest         , testCase "Tweak mult. secret key"   ecSecKeyTweakMulTest         ]@@ -300,40 +298,6 @@     pub = fst $ B16.decode         "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd447051221\         \3d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"--ecSecKeyExportTest :: Assertion-ecSecKeyExportTest = do-    ret <- liftIO $ alloca $ \k ->-        allocaBytes 279 $ \o -> alloca $ \ol -> do-            poke ol 279-            poke k key-            x <- signCtx-            ecSecKeyExport x o ol k uncompressed-    assertBool "successful secret key BER serialization" $ isSuccess ret-  where-    key = SecKey32 $ fst $ B16.decode-        "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"--ecSecKeyImportTest :: Assertion-ecSecKeyImportTest = do-    (ret, dec) <- liftIO $ do-        x <- signCtx-        ber <- allocaBytes 279 $ \o -> alloca $ \ol -> alloca $ \k -> do-            poke ol 279-            poke k key-            rets <- ecSecKeyExport x o ol k uncompressed-            unless (isSuccess rets) $ error "failed to serialize key"-            len <- fromIntegral <$> peek ol-            packCStringLen (castPtr o, len)-        useAsCStringLen ber $ \(b, bl) -> alloca $ \k -> do-            ret <- ecSecKeyImport x k (castPtr b) (fromIntegral bl)-            dec <- peek k-            return (ret, dec)-    assertBool "successful secret key BER deserialization" $ isSuccess ret-    assertEqual "keys match" key dec-  where-    key = SecKey32 $ fst $ B16.decode-        "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"  ecSecKeyTweakAddTest :: Assertion ecSecKeyTweakAddTest = do
haskell/test/Crypto/Secp256k1/Tests.hs view
@@ -1,10 +1,8 @@ module Crypto.Secp256k1.Tests (tests) where  import           Crypto.Secp256k1-import qualified Data.Binary                          as Bin import qualified Data.ByteString.Base16               as B16 import qualified Data.ByteString.Char8                as B8-import qualified Data.ByteString.Lazy                 as BL import           Data.Maybe                           (fromJust) import           Data.String                          (fromString) import           Data.String.Conversions              (cs)@@ -123,9 +121,9 @@   where     fg = signMsg fk fm -serializeSecKeyTest :: (SecKey, Bool) -> Bool-serializeSecKeyTest (fk, b) =-    case importSecKey $ exportSecKey b fk of+serializeSecKeyTest :: SecKey -> Bool+serializeSecKeyTest fk =+    case secKey $ getSecKey fk of         Just fk' -> fk == fk'         Nothing -> False 
include/secp256k1.h view
@@ -147,12 +147,23 @@ #  define SECP256K1_ARG_NONNULL(_x) # endif +/** All flags' lower 8 bits indicate what they're for. Do not use directly. */+#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1)+#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0)+#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1)+/** The higher bits contain the actual data. Do not use directly. */+#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8)+#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9)+#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8)+ /** Flags to pass to secp256k1_context_create. */-# define SECP256K1_CONTEXT_VERIFY (1 << 0)-# define SECP256K1_CONTEXT_SIGN   (1 << 1)+#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY)+#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)+#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT)  /** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */-# define SECP256K1_EC_COMPRESSED  (1 << 0)+#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION)+#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION)  /** Create a secp256k1 context object.  *@@ -261,7 +272,7 @@  *  In:   pubkey:     a pointer to a secp256k1_pubkey containing an initialized  *                    public key.  *        flags:      SECP256K1_EC_COMPRESSED if serialization should be in- *                    compressed format.+ *                    compressed format, otherwise SECP256K1_EC_UNCOMPRESSED.  */ SECP256K1_API int secp256k1_ec_pubkey_serialize(     const secp256k1_context* ctx,@@ -476,55 +487,6 @@     const secp256k1_context* ctx,     secp256k1_pubkey *pubkey,     const unsigned char *seckey-) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);--/** Export a private key in BER format.- *- *  Returns: 1 if the private key was valid.- *  Args: ctx:        pointer to a context object, initialized for signing (cannot- *                    be NULL)- *  Out: privkey:     pointer to an array for storing the private key in BER.- *                    Should have space for 279 bytes, and cannot be NULL.- *       privkeylen:  Pointer to an int where the length of the private key in- *                    privkey will be stored.- *  In:  seckey:      pointer to a 32-byte secret key to export.- *       flags:       SECP256K1_EC_COMPRESSED if the key should be exported in- *                    compressed format.- *- *  This function is purely meant for compatibility with applications that- *  require BER encoded keys. When working with secp256k1-specific code, the- *  simple 32-byte private keys are sufficient.- *- *  Note that this function does not guarantee correct DER output. It is- *  guaranteed to be parsable by secp256k1_ec_privkey_import.- */-SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export(-    const secp256k1_context* ctx,-    unsigned char *privkey,-    size_t *privkeylen,-    const unsigned char *seckey,-    unsigned int flags-) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);--/** Import a private key in DER format.- * Returns: 1 if a private key was extracted.- * Args: ctx:        pointer to a context object (cannot be NULL).- * Out:  seckey:     pointer to a 32-byte array for storing the private key.- *                   (cannot be NULL).- * In:   privkey:    pointer to a private key in DER format (cannot be NULL).- *       privkeylen: length of the DER private key pointed to be privkey.- *- * This function will accept more than just strict DER, and even allow some BER- * violations. The public key stored inside the DER-encoded private key is not- * verified for correctness, nor are the curve parameters. Use this function- * only if you know in advance it is supposed to contain a secp256k1 private- * key.- */-SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_import(-    const secp256k1_context* ctx,-    unsigned char *seckey,-    const unsigned char *privkey,-    size_t privkeylen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);  /** Tweak a private key by adding tweak to it.
secp256k1.cabal view
@@ -1,12 +1,12 @@ name:                secp256k1-version:             0.4.0+version:             0.4.1 synopsis:            secp256k1 bindings for Haskell description:         Please see README.md homepage:            http://github.com/haskoin/secp256k1#readme license:             MIT license-file:        COPYING author:              Pieter Wuille-maintainer:          root@haskoin.com+maintainer:          Jean-Pierre Rupp <root@haskoin.com> copyright:           (c) 2013 Pieter Wuille category:            Crypto build-type:          Custom
src/ecdsa.h view
@@ -17,6 +17,5 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s); static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid);-static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid);  #endif
src/ecdsa_impl.h view
@@ -238,11 +238,11 @@      *  secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test.      */     if (secp256k1_gej_eq_x_var(&xr, &pr)) {-        /* xr.x == xr * xr.z^2 mod p, so the signature is valid. */+        /* xr * pr.z^2 mod p == pr.x, so the signature is valid. */         return 1;     }     if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_const_p_minus_order) >= 0) {-        /* xr + p >= n, so we can skip testing the second case. */+        /* xr + n >= p, so we can skip testing the second case. */         return 0;     }     secp256k1_fe_add(&xr, &secp256k1_ecdsa_const_order_as_fe);@@ -253,39 +253,6 @@     return 0; } -static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) {-    unsigned char brx[32];-    secp256k1_fe fx;-    secp256k1_ge x;-    secp256k1_gej xj;-    secp256k1_scalar rn, u1, u2;-    secp256k1_gej qj;--    if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) {-        return 0;-    }--    secp256k1_scalar_get_b32(brx, sigr);-    VERIFY_CHECK(secp256k1_fe_set_b32(&fx, brx)); /* brx comes from a scalar, so is less than the order; certainly less than p */-    if (recid & 2) {-        if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) {-            return 0;-        }-        secp256k1_fe_add(&fx, &secp256k1_ecdsa_const_order_as_fe);-    }-    if (!secp256k1_ge_set_xo_var(&x, &fx, recid & 1)) {-        return 0;-    }-    secp256k1_gej_set_ge(&xj, &x);-    secp256k1_scalar_inverse_var(&rn, sigr);-    secp256k1_scalar_mul(&u1, &rn, message);-    secp256k1_scalar_negate(&u1, &u1);-    secp256k1_scalar_mul(&u2, &rn, sigs);-    secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1);-    secp256k1_ge_set_gej_var(pubkey, &qj);-    return !secp256k1_gej_is_infinity(&qj);-}- static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) {     unsigned char b[32];     secp256k1_gej rp;@@ -301,6 +268,7 @@     secp256k1_scalar_set_b32(sigr, b, &overflow);     if (secp256k1_scalar_is_zero(sigr)) {         /* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature. */+        /* This branch is cryptographically unreachable as hitting it requires finding the discrete log of P.x = N. */         secp256k1_gej_clear(&rp);         secp256k1_ge_clear(&r);         return 0;
src/eckey.h view
@@ -15,10 +15,7 @@ #include "ecmult_gen.h"  static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size);-static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, unsigned int flags);--static int secp256k1_eckey_privkey_parse(secp256k1_scalar *key, const unsigned char *privkey, size_t privkeylen);-static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context *ctx, unsigned char *privkey, size_t *privkeylen, const secp256k1_scalar *key, unsigned int flags);+static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed);  static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak);
src/eckey_impl.h view
@@ -33,123 +33,20 @@     } } -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, unsigned int flags) {+static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) {     if (secp256k1_ge_is_infinity(elem)) {         return 0;     }     secp256k1_fe_normalize_var(&elem->x);     secp256k1_fe_normalize_var(&elem->y);     secp256k1_fe_get_b32(&pub[1], &elem->x);-    if (flags & SECP256K1_EC_COMPRESSED) {+    if (compressed) {         *size = 33;         pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00);     } else {         *size = 65;         pub[0] = 0x04;         secp256k1_fe_get_b32(&pub[33], &elem->y);-    }-    return 1;-}--static int secp256k1_eckey_privkey_parse(secp256k1_scalar *key, const unsigned char *privkey, size_t privkeylen) {-    unsigned char c[32] = {0};-    const unsigned char *end = privkey + privkeylen;-    int lenb = 0;-    int len = 0;-    int overflow = 0;-    /* sequence header */-    if (end < privkey+1 || *privkey != 0x30) {-        return 0;-    }-    privkey++;-    /* sequence length constructor */-    if (end < privkey+1 || !(*privkey & 0x80)) {-        return 0;-    }-    lenb = *privkey & ~0x80; privkey++;-    if (lenb < 1 || lenb > 2) {-        return 0;-    }-    if (end < privkey+lenb) {-        return 0;-    }-    /* sequence length */-    len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0);-    privkey += lenb;-    if (end < privkey+len) {-        return 0;-    }-    /* sequence element 0: version number (=1) */-    if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) {-        return 0;-    }-    privkey += 3;-    /* sequence element 1: octet string, up to 32 bytes */-    if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) {-        return 0;-    }-    memcpy(c + 32 - privkey[1], privkey + 2, privkey[1]);-    secp256k1_scalar_set_b32(key, c, &overflow);-    memset(c, 0, 32);-    return !overflow;-}--static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context *ctx, unsigned char *privkey, size_t *privkeylen, const secp256k1_scalar *key, unsigned int flags) {-    secp256k1_gej rp;-    secp256k1_ge r;-    size_t pubkeylen = 0;-    secp256k1_ecmult_gen(ctx, &rp, key);-    secp256k1_ge_set_gej(&r, &rp);-    if (flags & SECP256K1_EC_COMPRESSED) {-        static const unsigned char begin[] = {-            0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20-        };-        static const unsigned char middle[] = {-            0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,-            0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,-            0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,-            0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,-            0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,-            0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,-            0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,-            0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,-            0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00-        };-        unsigned char *ptr = privkey;-        memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);-        secp256k1_scalar_get_b32(ptr, key); ptr += 32;-        memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);-        if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 1)) {-            return 0;-        }-        ptr += pubkeylen;-        *privkeylen = ptr - privkey;-    } else {-        static const unsigned char begin[] = {-            0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20-        };-        static const unsigned char middle[] = {-            0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,-            0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,-            0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,-            0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,-            0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,-            0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,-            0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11,-            0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10,-            0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,-            0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,-            0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00-        };-        unsigned char *ptr = privkey;-        memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);-        secp256k1_scalar_get_b32(ptr, key); ptr += 32;-        memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);-        if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 0)) {-            return 0;-        }-        ptr += pubkeylen;-        *privkeylen = ptr - privkey;     }     return 1; }
src/ecmult_gen_impl.h view
@@ -40,8 +40,13 @@         static const unsigned char nums_b32[33] = "The scalar for this x is unknown";         secp256k1_fe nums_x;         secp256k1_ge nums_ge;-        VERIFY_CHECK(secp256k1_fe_set_b32(&nums_x, nums_b32));-        VERIFY_CHECK(secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0));+        int r;+        r = secp256k1_fe_set_b32(&nums_x, nums_b32);+        (void)r;+        VERIFY_CHECK(r);+        r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0);+        (void)r;+        VERIFY_CHECK(r);         secp256k1_gej_set_ge(&nums_gej, &nums_ge);         /* Add G to make the bits in x uniformly distributed. */         secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL);@@ -182,7 +187,7 @@         secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);         retry = !secp256k1_fe_set_b32(&s, nonce32);         retry |= secp256k1_fe_is_zero(&s);-    } while (retry);+    } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */     /* Randomize the projection to defend against multiplier sidechannels. */     secp256k1_gej_rescale(&ctx->initial, &s);     secp256k1_fe_clear(&s);@@ -191,7 +196,7 @@         secp256k1_scalar_set_b32(&b, nonce32, &retry);         /* A blinding value of 0 works, but would undermine the projection hardening. */         retry |= secp256k1_scalar_is_zero(&b);-    } while (retry);+    } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */     secp256k1_rfc6979_hmac_sha256_finalize(&rng);     memset(nonce32, 0, 32);     secp256k1_ecmult_gen(ctx, &gb, &b);
src/field_impl.h view
@@ -224,6 +224,7 @@         0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F     };     unsigned char b[32];+    int res;     secp256k1_fe c = *a;     secp256k1_fe_normalize_var(&c);     secp256k1_fe_get_b32(b, &c);@@ -231,7 +232,9 @@     secp256k1_num_set_bin(&m, prime, 32);     secp256k1_num_mod_inverse(&n, &n, &m);     secp256k1_num_get_bin(b, 32, &n);-    VERIFY_CHECK(secp256k1_fe_set_b32(r, b));+    res = secp256k1_fe_set_b32(r, b);+    (void)res;+    VERIFY_CHECK(res);     /* Verify the result is the (unique) valid inverse using non-GMP code. */     secp256k1_fe_mul(&c, &c, r);     secp256k1_fe_add(&c, &negone);
src/modules/recovery/main_impl.h view
@@ -84,6 +84,42 @@     return 1; } +static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) {+    unsigned char brx[32];+    secp256k1_fe fx;+    secp256k1_ge x;+    secp256k1_gej xj;+    secp256k1_scalar rn, u1, u2;+    secp256k1_gej qj;+    int r;++    if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) {+        return 0;+    }++    secp256k1_scalar_get_b32(brx, sigr);+    r = secp256k1_fe_set_b32(&fx, brx);+    (void)r;+    VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */+    if (recid & 2) {+        if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) {+            return 0;+        }+        secp256k1_fe_add(&fx, &secp256k1_ecdsa_const_order_as_fe);+    }+    if (!secp256k1_ge_set_xo_var(&x, &fx, recid & 1)) {+        return 0;+    }+    secp256k1_gej_set_ge(&xj, &x);+    secp256k1_scalar_inverse_var(&rn, sigr);+    secp256k1_scalar_mul(&u1, &rn, message);+    secp256k1_scalar_negate(&u1, &u1);+    secp256k1_scalar_mul(&u2, &rn, sigs);+    secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1);+    secp256k1_ge_set_gej_var(pubkey, &qj);+    return !secp256k1_gej_is_infinity(&qj);+}+ int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) {     secp256k1_scalar r, s;     secp256k1_scalar sec, non, msg;
src/num_gmp_impl.h view
@@ -70,6 +70,7 @@  static void secp256k1_num_sub_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) {     mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs);+    (void)c;     VERIFY_CHECK(c == 0);     r->limbs = a->limbs;     while (r->limbs > 1 && r->data[r->limbs-1]==0) {@@ -125,6 +126,7 @@     }     sn = NUM_LIMBS+1;     gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs);+    (void)gn;     VERIFY_CHECK(gn == 1);     VERIFY_CHECK(g[0] == 1);     r->neg = a->neg ^ m->neg;
src/secp256k1.c view
@@ -62,13 +62,20 @@     ret->illegal_callback = default_illegal_callback;     ret->error_callback = default_error_callback; +    if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) {+            secp256k1_callback_call(&ret->illegal_callback,+                                    "Invalid flags");+            free(ret);+            return NULL;+    }+     secp256k1_ecmult_context_init(&ret->ecmult_ctx);     secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); -    if (flags & SECP256K1_CONTEXT_SIGN) {+    if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {         secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback);     }-    if (flags & SECP256K1_CONTEXT_VERIFY) {+    if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {         secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback);     } @@ -166,8 +173,9 @@     ARG_CHECK(output != NULL);     ARG_CHECK(outputlen != NULL);     ARG_CHECK(pubkey != NULL);+    ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION);     return (secp256k1_pubkey_load(ctx, &Q, pubkey) &&-            secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, flags));+            secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, flags & SECP256K1_FLAGS_BIT_COMPRESSION)); }  static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) {@@ -300,8 +308,10 @@    /* We feed a byte array to the PRNG as input, consisting of:     * - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d.     * - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data.-    * - optionally 16 extra bytes with the algorithm name (the extra data bytes-    *   are set to zeroes when not present, while the algorithm name is).+    * - optionally 16 extra bytes with the algorithm name.+    * Because the arguments have distinct fixed lengths it is not possible for+    *  different argument mixtures to emulate each other and result in the same+    *  nonces.     */    memcpy(keydata, key32, 32);    memcpy(keydata + 32, msg32, 32);@@ -310,9 +320,8 @@        keylen = 96;    }    if (algo16 != NULL) {-       memset(keydata + keylen, 0, 96 - keylen);-       memcpy(keydata + 96, algo16, 16);-       keylen = 112;+       memcpy(keydata + keylen, algo16, 16);+       keylen += 16;    }    secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen);    memset(keydata, 0, sizeof(keydata));@@ -399,13 +408,13 @@      secp256k1_scalar_set_b32(&sec, seckey, &overflow);     ret = (!overflow) & (!secp256k1_scalar_is_zero(&sec));-    secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec);-    secp256k1_ge_set_gej(&p, &pj);-    secp256k1_pubkey_save(pubkey, &p);-    secp256k1_scalar_clear(&sec);-    if (!ret) {-        memset(pubkey, 0, sizeof(*pubkey));+    memset(pubkey, 0, sizeof(*pubkey));+    if (ret) {+        secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec);+        secp256k1_ge_set_gej(&p, &pj);+        secp256k1_pubkey_save(pubkey, &p);     }+    secp256k1_scalar_clear(&sec);     return ret; } @@ -423,6 +432,7 @@     secp256k1_scalar_set_b32(&sec, seckey, NULL);      ret = !overflow && secp256k1_eckey_privkey_tweak_add(&sec, &term);+    memset(seckey, 0, 32);     if (ret) {         secp256k1_scalar_get_b32(seckey, &sec);     }@@ -443,12 +453,13 @@     ARG_CHECK(tweak != NULL);      secp256k1_scalar_set_b32(&term, tweak, &overflow);-    if (!overflow && secp256k1_pubkey_load(ctx, &p, pubkey)) {-        ret = secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term);-        if (ret) {+    ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey);+    memset(pubkey, 0, sizeof(*pubkey));+    if (ret) {+        if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) {             secp256k1_pubkey_save(pubkey, &p);         } else {-            memset(pubkey, 0, sizeof(*pubkey));+            ret = 0;         }     } @@ -468,6 +479,7 @@     secp256k1_scalar_set_b32(&factor, tweak, &overflow);     secp256k1_scalar_set_b32(&sec, seckey, NULL);     ret = !overflow && secp256k1_eckey_privkey_tweak_mul(&sec, &factor);+    memset(seckey, 0, 32);     if (ret) {         secp256k1_scalar_get_b32(seckey, &sec);     }@@ -488,45 +500,16 @@     ARG_CHECK(tweak != NULL);      secp256k1_scalar_set_b32(&factor, tweak, &overflow);-    if (!overflow && secp256k1_pubkey_load(ctx, &p, pubkey)) {-        ret = secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor);-        if (ret) {+    ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey);+    memset(pubkey, 0, sizeof(*pubkey));+    if (ret) {+        if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) {             secp256k1_pubkey_save(pubkey, &p);         } else {-            memset(pubkey, 0, sizeof(*pubkey));+            ret = 0;         }     } -    return ret;-}--int secp256k1_ec_privkey_export(const secp256k1_context* ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, unsigned int flags) {-    secp256k1_scalar key;-    int ret = 0;-    VERIFY_CHECK(ctx != NULL);-    ARG_CHECK(seckey != NULL);-    ARG_CHECK(privkey != NULL);-    ARG_CHECK(privkeylen != NULL);-    ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));--    secp256k1_scalar_set_b32(&key, seckey, NULL);-    ret = secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, privkeylen, &key, flags);-    secp256k1_scalar_clear(&key);-    return ret;-}--int secp256k1_ec_privkey_import(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *privkey, size_t privkeylen) {-    secp256k1_scalar key;-    int ret = 0;-    ARG_CHECK(seckey != NULL);-    ARG_CHECK(privkey != NULL);-    (void)ctx;--    ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen);-    if (ret) {-        secp256k1_scalar_get_b32(seckey, &key);-    }-    secp256k1_scalar_clear(&key);     return ret; } 
src/tests.c view
@@ -25,6 +25,7 @@ #endif  #include "contrib/lax_der_parsing.h"+#include "contrib/lax_der_privatekey_parsing.h"  #if !defined(VG_CHECK) # if defined(VALGRIND)@@ -40,6 +41,22 @@ static int count = 64; static secp256k1_context *ctx = NULL; +static void counting_illegal_callback_fn(const char* str, void* data) {+    /* Dummy callback function that just counts. */+    int32_t *p;+    (void)str;+    p = data;+    (*p)++;+}++static void uncounting_illegal_callback_fn(const char* str, void* data) {+    /* Dummy callback function that just counts (backwards). */+    int32_t *p;+    (void)str;+    p = data;+    (*p)--;+}+ void random_field_element_test(secp256k1_fe *fe) {     do {         unsigned char b32[32];@@ -117,7 +134,12 @@ }  void run_context_tests(void) {-    secp256k1_context *none = secp256k1_context_create(0);+    secp256k1_pubkey pubkey;+    secp256k1_ecdsa_signature sig;+    unsigned char ctmp[32];+    int32_t ecount;+    int32_t ecount2;+    secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);     secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);     secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);     secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);@@ -127,6 +149,13 @@     secp256k1_scalar msg, key, nonce;     secp256k1_scalar sigr, sigs; +    ecount = 0;+    ecount2 = 10;+    secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);+    secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2);+    secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, NULL);+    CHECK(vrfy->error_callback.fn != sign->error_callback.fn);+     /*** clone and destroy all of them to make sure cloning was complete ***/     {         secp256k1_context *ctx_tmp;@@ -137,12 +166,54 @@         ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_destroy(ctx_tmp);     } +    /* Verify that the error callback makes it across the clone. */+    CHECK(vrfy->error_callback.fn != sign->error_callback.fn);+    /* And that it resets back to default. */+    secp256k1_context_set_error_callback(sign, NULL, NULL);+    CHECK(vrfy->error_callback.fn == sign->error_callback.fn);+     /*** attempt to use them ***/     random_scalar_order_test(&msg);     random_scalar_order_test(&key);     secp256k1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key);     secp256k1_ge_set_gej(&pub, &pubj); +    /* Verify context-type checking illegal-argument errors. */+    memset(ctmp, 1, 32);+    CHECK(secp256k1_ec_pubkey_create(vrfy, &pubkey, ctmp) == 0);+    CHECK(ecount == 1);+    VG_UNDEF(&pubkey, sizeof(pubkey));+    CHECK(secp256k1_ec_pubkey_create(sign, &pubkey, ctmp) == 1);+    VG_CHECK(&pubkey, sizeof(pubkey));+    CHECK(secp256k1_ecdsa_sign(vrfy, &sig, ctmp, ctmp, NULL, NULL) == 0);+    CHECK(ecount == 2);+    VG_UNDEF(&sig, sizeof(sig));+    CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1);+    VG_CHECK(&sig, sizeof(sig));+    CHECK(ecount2 == 10);+    CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 0);+    CHECK(ecount2 == 11);+    CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1);+    CHECK(ecount == 2);+    CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 0);+    CHECK(ecount2 == 12);+    CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1);+    CHECK(ecount == 2);+    CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0);+    CHECK(ecount2 == 13);+    CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);+    CHECK(ecount == 2);+    CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0);+    CHECK(ecount == 3);+    CHECK(secp256k1_context_randomize(sign, NULL) == 1);+    CHECK(ecount2 == 13);+    secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);+    secp256k1_context_set_illegal_callback(sign, NULL, NULL);++    /* This shouldn't leak memory, due to already-set tests. */+    secp256k1_ecmult_gen_context_build(&sign->ecmult_gen_ctx, NULL);+    secp256k1_ecmult_context_build(&vrfy->ecmult_ctx, NULL);+     /* obtain a working nonce */     do {         random_scalar_order_test(&nonce);@@ -1724,6 +1795,11 @@         test_constant_wnaf_negate(&n);         test_constant_wnaf(&n, 4 + (i % 10));     }+    secp256k1_scalar_set_int(&n, 0);+    CHECK(secp256k1_scalar_cond_negate(&n, 1) == -1);+    CHECK(secp256k1_scalar_is_zero(&n));+    CHECK(secp256k1_scalar_cond_negate(&n, 0) == 1);+    CHECK(secp256k1_scalar_is_zero(&n)); }  void test_ecmult_constants(void) {@@ -1836,22 +1912,6 @@ } #endif -static void counting_illegal_callback_fn(const char* str, void* data) {-    /* Dummy callback function that just counts. */-    int32_t *p;-    (void)str;-    p = data;-    (*p)++;-}--static void uncounting_illegal_callback_fn(const char* str, void* data) {-    /* Dummy callback function that just counts (backwards). */-    int32_t *p;-    (void)str;-    p = data;-    (*p)--;-}- void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvalid) {     unsigned char pubkeyc[65];     secp256k1_pubkey pubkey;@@ -1904,7 +1964,7 @@                     VG_CHECK(&pubkey, sizeof(pubkey));                     outl = 65;                     VG_UNDEF(pubkeyo, 65);-                    CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, 0) == 1);+                    CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1);                     VG_CHECK(pubkeyo, outl);                     CHECK(outl == 65);                     CHECK(pubkeyo[0] == 4);@@ -2228,6 +2288,175 @@     } } +void run_eckey_edge_case_test(void) {+    const unsigned char orderc[32] = {+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,+        0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,+        0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41+    };+    const unsigned char zeros[sizeof(secp256k1_pubkey)] = {0x00};+    unsigned char ctmp[32];+    unsigned char ctmp2[32];+    secp256k1_pubkey pubkey;+    secp256k1_pubkey pubkey2;+    int32_t ecount;+    /* Group order is too large, reject. */+    CHECK(secp256k1_ec_seckey_verify(ctx, orderc) == 0);+    VG_UNDEF(&pubkey, sizeof(pubkey));+    CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, orderc) == 0);+    VG_CHECK(&pubkey, sizeof(pubkey));+    CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);+    /* Maximum value is too large, reject. */+    memset(ctmp, 255, 32);+    CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0);+    memset(&pubkey, 1, sizeof(pubkey));+    VG_UNDEF(&pubkey, sizeof(pubkey));+    CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0);+    VG_CHECK(&pubkey, sizeof(pubkey));+    CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);+    /* Zero is too small, reject. */+    memset(ctmp, 0, 32);+    CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0);+    memset(&pubkey, 1, sizeof(pubkey));+    VG_UNDEF(&pubkey, sizeof(pubkey));+    CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0);+    VG_CHECK(&pubkey, sizeof(pubkey));+    CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);+    /* One must be accepted. */+    ctmp[31] = 0x01;+    CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1);+    memset(&pubkey, 0, sizeof(pubkey));+    VG_UNDEF(&pubkey, sizeof(pubkey));+    CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1);+    VG_CHECK(&pubkey, sizeof(pubkey));+    CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);+    /* Group order + 1 is too large, reject. */+    memcpy(ctmp, orderc, 32);+    ctmp[31] = 0x42;+    CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0);+    memset(&pubkey, 1, sizeof(pubkey));+    VG_UNDEF(&pubkey, sizeof(pubkey));+    CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0);+    VG_CHECK(&pubkey, sizeof(pubkey));+    CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);+    /* -1 must be accepted. */+    ctmp[31] = 0x40;+    CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1);+    memset(&pubkey, 0, sizeof(pubkey));+    VG_UNDEF(&pubkey, sizeof(pubkey));+    CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1);+    VG_CHECK(&pubkey, sizeof(pubkey));+    CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);+    /* Tweak of zero leaves the value changed. */+    memset(ctmp2, 0, 32);+    CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1);+    CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40);+    memcpy(&pubkey2, &pubkey, sizeof(pubkey));+    CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1);+    CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0);+    /* Multiply tweak of zero zeroizes the output. */+    CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, ctmp2) == 0);+    CHECK(memcmp(zeros, ctmp, 32) == 0);+    CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp2) == 0);+    CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0);+    memcpy(&pubkey, &pubkey2, sizeof(pubkey));+    /* Overflowing key tweak zeroizes. */+    memcpy(ctmp, orderc, 32);+    ctmp[31] = 0x40;+    CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, orderc) == 0);+    CHECK(memcmp(zeros, ctmp, 32) == 0);+    memcpy(ctmp, orderc, 32);+    ctmp[31] = 0x40;+    CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, orderc) == 0);+    CHECK(memcmp(zeros, ctmp, 32) == 0);+    memcpy(ctmp, orderc, 32);+    ctmp[31] = 0x40;+    CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, orderc) == 0);+    CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0);+    memcpy(&pubkey, &pubkey2, sizeof(pubkey));+    CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, orderc) == 0);+    CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0);+    memcpy(&pubkey, &pubkey2, sizeof(pubkey));+    /* Private key tweaks results in a key of zero. */+    ctmp2[31] = 1;+    CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 0);+    CHECK(memcmp(zeros, ctmp2, 32) == 0);+    ctmp2[31] = 1;+    CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0);+    CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0);+    memcpy(&pubkey, &pubkey2, sizeof(pubkey));+    /* Tweak computation wraps and results in a key of 1. */+    ctmp2[31] = 2;+    CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 1);+    CHECK(memcmp(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1);+    ctmp2[31] = 2;+    CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1);+    ctmp2[31] = 1;+    CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, ctmp2) == 1);+    CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0);+    /* Tweak mul * 2 = 1+1. */+    CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1);+    ctmp2[31] = 2;+    CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 1);+    CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0);+    /* Test argument errors. */+    ecount = 0;+    secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);+    CHECK(ecount == 0);+    /* Zeroize pubkey on parse error. */+    memset(&pubkey, 0, 32);+    CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0);+    CHECK(ecount == 1);+    CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0);+    memcpy(&pubkey, &pubkey2, sizeof(pubkey));+    memset(&pubkey2, 0, 32);+    CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 0);+    CHECK(ecount == 2);+    CHECK(memcmp(&pubkey2, zeros, sizeof(pubkey2)) == 0);+    /* Plain argument errors. */+    ecount = 0;+    CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1);+    CHECK(ecount == 0);+    CHECK(secp256k1_ec_seckey_verify(ctx, NULL) == 0);+    CHECK(ecount == 1);+    ecount = 0;+    memset(ctmp2, 0, 32);+    ctmp2[31] = 4;+    CHECK(secp256k1_ec_pubkey_tweak_add(ctx, NULL, ctmp2) == 0);+    CHECK(ecount == 1);+    CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, NULL) == 0);+    CHECK(ecount == 2);+    ecount = 0;+    memset(ctmp2, 0, 32);+    ctmp2[31] = 4;+    CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, NULL, ctmp2) == 0);+    CHECK(ecount == 1);+    CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, NULL) == 0);+    CHECK(ecount == 2);+    ecount = 0;+    memset(ctmp2, 0, 32);+    CHECK(secp256k1_ec_privkey_tweak_add(ctx, NULL, ctmp2) == 0);+    CHECK(ecount == 1);+    CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, NULL) == 0);+    CHECK(ecount == 2);+    ecount = 0;+    memset(ctmp2, 0, 32);+    ctmp2[31] = 1;+    CHECK(secp256k1_ec_privkey_tweak_mul(ctx, NULL, ctmp2) == 0);+    CHECK(ecount == 1);+    CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, NULL) == 0);+    CHECK(ecount == 2);+    ecount = 0;+    CHECK(secp256k1_ec_pubkey_create(ctx, NULL, ctmp) == 0);+    CHECK(ecount == 1);+    memset(&pubkey, 1, sizeof(pubkey));+    CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0);+    CHECK(ecount == 2);+    CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);+    secp256k1_context_set_illegal_callback(ctx, NULL, NULL);+}+ void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *key, const secp256k1_scalar *msg, int *recid) {     secp256k1_scalar nonce;     do {@@ -2346,13 +2575,13 @@     CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1);      /* Verify exporting and importing public key. */-    CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand_bits(1)) == 1);+    CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED));     memset(&pubkey, 0, sizeof(pubkey));     CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1);      /* Verify private key import and export. */-    CHECK(secp256k1_ec_privkey_export(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1) ? SECP256K1_EC_COMPRESSED : 0);-    CHECK(secp256k1_ec_privkey_import(ctx, privkey2, seckey, seckeylen) == 1);+    CHECK(secp256k1_ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1));+    CHECK(secp256k1_ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1);     CHECK(memcmp(privkey, privkey2, 32) == 0);      /* Optionally tweak the keys using addition. */@@ -2469,7 +2698,7 @@         size_t size = len;         firstb = in[0];         /* If the pubkey can be parsed, it should round-trip... */-        CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, (len == 33) ? SECP256K1_EC_COMPRESSED : 0));+        CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, len == 33));         CHECK(size == len);         CHECK(memcmp(&in[1], &out[1], len-1) == 0);         /* ... except for the type of hybrid inputs. */@@ -2838,7 +3067,6 @@     } } - /* Tests several edge cases. */ void test_ecdsa_edge_cases(void) {     int t;@@ -2860,11 +3088,159 @@         CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);     } -    /*Signature where s would be zero.*/+    /* Verify signature with r of zero fails. */     {-        unsigned char signature[72];+        const unsigned char pubkey_mods_zero[33] = {+            0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,+            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,+            0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0,+            0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41,+            0x41+        };+        secp256k1_ge key;+        secp256k1_scalar msg;+        secp256k1_scalar sr, ss;+        secp256k1_scalar_set_int(&ss, 1);+        secp256k1_scalar_set_int(&msg, 0);+        secp256k1_scalar_set_int(&sr, 0);+        CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33));+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);+    }++    /* Verify signature with s of zero fails. */+    {+        const unsigned char pubkey[33] = {+            0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+            0x01+        };+        secp256k1_ge key;+        secp256k1_scalar msg;+        secp256k1_scalar sr, ss;+        secp256k1_scalar_set_int(&ss, 0);+        secp256k1_scalar_set_int(&msg, 0);+        secp256k1_scalar_set_int(&sr, 1);+        CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);+    }++    /* Verify signature with message 0 passes. */+    {+        const unsigned char pubkey[33] = {+            0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+            0x02+        };+        const unsigned char pubkey2[33] = {+            0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,+            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,+            0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0,+            0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41,+            0x43+        };+        secp256k1_ge key;+        secp256k1_ge key2;+        secp256k1_scalar msg;+        secp256k1_scalar sr, ss;+        secp256k1_scalar_set_int(&ss, 2);+        secp256k1_scalar_set_int(&msg, 0);+        secp256k1_scalar_set_int(&sr, 2);+        CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));+        CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33));+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);+        secp256k1_scalar_negate(&ss, &ss);+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);+        secp256k1_scalar_set_int(&ss, 1);+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0);+    }++    /* Verify signature with message 1 passes. */+    {+        const unsigned char pubkey[33] = {+            0x02, 0x14, 0x4e, 0x5a, 0x58, 0xef, 0x5b, 0x22,+            0x6f, 0xd2, 0xe2, 0x07, 0x6a, 0x77, 0xcf, 0x05,+            0xb4, 0x1d, 0xe7, 0x4a, 0x30, 0x98, 0x27, 0x8c,+            0x93, 0xe6, 0xe6, 0x3c, 0x0b, 0xc4, 0x73, 0x76,+            0x25+        };+        const unsigned char pubkey2[33] = {+            0x02, 0x8a, 0xd5, 0x37, 0xed, 0x73, 0xd9, 0x40,+            0x1d, 0xa0, 0x33, 0xd2, 0xdc, 0xf0, 0xaf, 0xae,+            0x34, 0xcf, 0x5f, 0x96, 0x4c, 0x73, 0x28, 0x0f,+            0x92, 0xc0, 0xf6, 0x9d, 0xd9, 0xb2, 0x09, 0x10,+            0x62+        };+        const unsigned char csr[32] = {+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,+            0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4,+            0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xeb+        };+        secp256k1_ge key;+        secp256k1_ge key2;+        secp256k1_scalar msg;+        secp256k1_scalar sr, ss;+        secp256k1_scalar_set_int(&ss, 1);+        secp256k1_scalar_set_int(&msg, 1);+        secp256k1_scalar_set_b32(&sr, csr, NULL);+        CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));+        CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33));+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);+        secp256k1_scalar_negate(&ss, &ss);+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);+        secp256k1_scalar_set_int(&ss, 2);+        secp256k1_scalar_inverse_var(&ss, &ss);+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0);+    }++    /* Verify signature with message -1 passes. */+    {+        const unsigned char pubkey[33] = {+            0x03, 0xaf, 0x97, 0xff, 0x7d, 0x3a, 0xf6, 0xa0,+            0x02, 0x94, 0xbd, 0x9f, 0x4b, 0x2e, 0xd7, 0x52,+            0x28, 0xdb, 0x49, 0x2a, 0x65, 0xcb, 0x1e, 0x27,+            0x57, 0x9c, 0xba, 0x74, 0x20, 0xd5, 0x1d, 0x20,+            0xf1+        };+        const unsigned char csr[32] = {+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,+            0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4,+            0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xee+        };+        secp256k1_ge key;+        secp256k1_scalar msg;+        secp256k1_scalar sr, ss;+        secp256k1_scalar_set_int(&ss, 1);+        secp256k1_scalar_set_int(&msg, 1);+        secp256k1_scalar_negate(&msg, &msg);+        secp256k1_scalar_set_b32(&sr, csr, NULL);+        CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);+        secp256k1_scalar_negate(&ss, &ss);+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);+        secp256k1_scalar_set_int(&ss, 3);+        secp256k1_scalar_inverse_var(&ss, &ss);+        CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);+    }++    /* Signature where s would be zero. */+    {+        secp256k1_pubkey pubkey;         size_t siglen;-        const unsigned char nonce[32] = {+        int32_t ecount;+        unsigned char signature[72];+        static const unsigned char nonce[32] = {             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,@@ -2888,15 +3264,40 @@             0xb8, 0x12, 0xe0, 0x0b, 0x81, 0x7a, 0x77, 0x62,             0x65, 0xdf, 0xdd, 0x31, 0xb9, 0x3e, 0x29, 0xa9,         };+        ecount = 0;+        secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);         CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 0);         CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 0);         msg[31] = 0xaa;         CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 1);+        CHECK(ecount == 0);+        CHECK(secp256k1_ecdsa_sign(ctx, NULL, msg, key, precomputed_nonce_function, nonce2) == 0);+        CHECK(ecount == 1);+        CHECK(secp256k1_ecdsa_sign(ctx, &sig, NULL, key, precomputed_nonce_function, nonce2) == 0);+        CHECK(ecount == 2);+        CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, NULL, precomputed_nonce_function, nonce2) == 0);+        CHECK(ecount == 3);         CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 1);+        CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, key) == 1);+        CHECK(secp256k1_ecdsa_verify(ctx, NULL, msg, &pubkey) == 0);+        CHECK(ecount == 4);+        CHECK(secp256k1_ecdsa_verify(ctx, &sig, NULL, &pubkey) == 0);+        CHECK(ecount == 5);+        CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, NULL) == 0);+        CHECK(ecount == 6);+        CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 1);         siglen = 72;+        CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, NULL, &siglen, &sig) == 0);+        CHECK(ecount == 7);+        CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, NULL, &sig) == 0);+        CHECK(ecount == 8);+        CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, NULL) == 0);+        CHECK(ecount == 9);         CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 1);         siglen = 10;         CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 0);+        CHECK(ecount == 9);+        secp256k1_context_set_illegal_callback(ctx, NULL, NULL);     }      /* Nonce function corner cases. */@@ -2960,6 +3361,34 @@         key[0] = 0;     } +    {+        /* Check that optional nonce arguments do not have equivilent effect. */+        const unsigned char zeros[32] = {0};+        unsigned char nonce[32];+        unsigned char nonce2[32];+        unsigned char nonce3[32];+        unsigned char nonce4[32];+        VG_UNDEF(nonce,32);+        VG_UNDEF(nonce2,32);+        VG_UNDEF(nonce3,32);+        VG_UNDEF(nonce4,32);+        CHECK(nonce_function_rfc6979(nonce, zeros, zeros, NULL, NULL, 0) == 1);+        VG_CHECK(nonce,32);+        CHECK(nonce_function_rfc6979(nonce2, zeros, zeros, zeros, NULL, 0) == 1);+        VG_CHECK(nonce2,32);+        CHECK(nonce_function_rfc6979(nonce3, zeros, zeros, NULL, (void *)zeros, 0) == 1);+        VG_CHECK(nonce3,32);+        CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1);+        VG_CHECK(nonce4,32);+        CHECK(memcmp(nonce, nonce2, 32) != 0);+        CHECK(memcmp(nonce, nonce3, 32) != 0);+        CHECK(memcmp(nonce, nonce4, 32) != 0);+        CHECK(memcmp(nonce2, nonce3, 32) != 0);+        CHECK(memcmp(nonce2, nonce4, 32) != 0);+        CHECK(memcmp(nonce3, nonce4, 32) != 0);+    }++     /* Privkey export where pubkey is the point at infinity. */     {         unsigned char privkey[300];@@ -2970,9 +3399,9 @@             0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41,         };         size_t outlen = 300;-        CHECK(!secp256k1_ec_privkey_export(ctx, privkey, &outlen, seckey, 0));+        CHECK(!secp256k1_ec_privkey_export_der(ctx, privkey, &outlen, seckey, 0));         outlen = 300;-        CHECK(!secp256k1_ec_privkey_export(ctx, privkey, &outlen, seckey, SECP256K1_EC_COMPRESSED));+        CHECK(!secp256k1_ec_privkey_export_der(ctx, privkey, &outlen, seckey, 1));     } } @@ -2987,7 +3416,7 @@     const unsigned char* pbegin = privkey;     int compr = secp256k1_rand_bits(1);     EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);-    CHECK(secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, &privkeylen, key, compr ? SECP256K1_EC_COMPRESSED : 0));+    CHECK(secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, &privkeylen, key, compr));     CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen));     CHECK(EC_KEY_check_key(ec_key));     return ec_key;@@ -3137,8 +3566,11 @@     run_endomorphism_tests(); #endif -    /* EC point parser test*/+    /* EC point parser test */     run_ec_pubkey_parse_test();++    /* EC key edge cases */+    run_eckey_edge_case_test();  #ifdef ENABLE_MODULE_ECDH     /* ecdh tests */