]> Git Repo - secp256k1.git/blobdiff - contrib/lax_der_parsing.h
Merge #930: Add ARM32/ARM64 CI
[secp256k1.git] / contrib / lax_der_parsing.h
index 53aafbc4b497f6dbbbb461c270d36eca71e00afc..034a38e6a0e1d0fb303c78bb9fd0ac20ecd44358 100644 (file)
@@ -1,10 +1,17 @@
-/**********************************************************************
- * Copyright (c) 2015 Pieter Wuille                                   *
- * Distributed under the MIT software license, see the accompanying   *
- * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
- **********************************************************************/
-
-/* This file contains a code snippet that parses DER with various errors and
+/***********************************************************************
+ * Copyright (c) 2015 Pieter Wuille                                    *
+ * Distributed under the MIT software license, see the accompanying    *
+ * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
+ ***********************************************************************/
+
+/****
+ * Please do not link this file directly. It is not part of the libsecp256k1
+ * project and does not promise any stability in its API, functionality or
+ * presence. Projects which use this code should instead copy this header
+ * and its accompanying .c file directly into their codebase.
+ ****/
+
+/* This file defines a function that parses DER with various errors and
  * violations. This is not a part of the library itself, because the allowed
  * violations are chosen arbitrarily and do not follow or establish any
  * standard.
  *   8.3.1.
  */
 
-#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_
-#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_
+#ifndef SECP256K1_CONTRIB_LAX_DER_PARSING_H
+#define SECP256K1_CONTRIB_LAX_DER_PARSING_H
 
-#include <string.h>
+/* #include secp256k1.h only when it hasn't been included yet.
+   This enables this file to be #included directly in other project
+   files (such as tests.c) without the need to set an explicit -I flag,
+   which would be necessary to locate secp256k1.h. */
+#ifndef SECP256K1_H
 #include <secp256k1.h>
+#endif
 
-static int secp256k1_ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen);
-
-static int secp256k1_ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {
-    size_t rpos, rlen, spos, slen;
-    size_t pos = 0;
-    size_t lenbyte;
-    unsigned char tmpsig[64] = {0};
-    int overflow = 0;
-
-    /* Hack to initialize sig with a correctly-parsed but invalid signature. */
-    secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
-
-    /* Sequence tag byte */
-    if (pos == inputlen || input[pos] != 0x30) {
-        return 0;
-    }
-    pos++;
-
-    /* Sequence length bytes */
-    if (pos == inputlen) {
-        return 0;
-    }
-    lenbyte = input[pos++];
-    if (lenbyte & 0x80) {
-        lenbyte -= 0x80;
-        if (pos + lenbyte > inputlen) {
-            return 0;
-        }
-        pos += lenbyte;
-    }
-
-    /* Integer tag byte for R */
-    if (pos == inputlen || input[pos] != 0x02) {
-        return 0;
-    }
-    pos++;
-
-    /* Integer length for R */
-    if (pos == inputlen) {
-        return 0;
-    }
-    lenbyte = input[pos++];
-    if (lenbyte & 0x80) {
-        lenbyte -= 0x80;
-        if (pos + lenbyte > inputlen) {
-            return 0;
-        }
-        while (lenbyte > 0 && input[pos] == 0) {
-            pos++;
-            lenbyte--;
-        }
-        if (lenbyte >= sizeof(size_t)) {
-            return 0;
-        }
-        rlen = 0;
-        while (lenbyte > 0) {
-            rlen = (rlen << 8) + input[pos];
-            pos++;
-            lenbyte--;
-        }
-    } else {
-        rlen = lenbyte;
-    }
-    if (rlen > inputlen - pos) {
-        return 0;
-    }
-    rpos = pos;
-    pos += rlen;
-
-    /* Integer tag byte for S */
-    if (pos == inputlen || input[pos] != 0x02) {
-        return 0;
-    }
-    pos++;
-
-    /* Integer length for S */
-    if (pos == inputlen) {
-        return 0;
-    }
-    lenbyte = input[pos++];
-    if (lenbyte & 0x80) {
-        lenbyte -= 0x80;
-        if (pos + lenbyte > inputlen) {
-            return 0;
-        }
-        while (lenbyte > 0 && input[pos] == 0) {
-            pos++;
-            lenbyte--;
-        }
-        if (lenbyte >= sizeof(size_t)) {
-            return 0;
-        }
-        slen = 0;
-        while (lenbyte > 0) {
-            slen = (slen << 8) + input[pos];
-            pos++;
-            lenbyte--;
-        }
-    } else {
-        slen = lenbyte;
-    }
-    if (slen > inputlen - pos) {
-        return 0;
-    }
-    spos = pos;
-    pos += slen;
-
-    /* Ignore leading zeroes in R */
-    while (rlen > 0 && input[rpos] == 0) {
-        rlen--;
-        rpos++;
-    }
-    /* Copy R value */
-    if (rlen > 32) {
-        overflow = 1;
-    } else {
-        memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
-    }
-
-    /* Ignore leading zeroes in S */
-    while (slen > 0 && input[spos] == 0) {
-        slen--;
-        spos++;
-    }
-    /* Copy S value */
-    if (slen > 32) {
-        overflow = 1;
-    } else {
-        memcpy(tmpsig + 64 - slen, input + spos, slen);
-    }
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-    if (!overflow) {
-        overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
-    }
-    if (overflow) {
-        memset(tmpsig, 0, 64);
-        secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
-    }
-    return 1;
+/** Parse a signature in "lax DER" format
+ *
+ *  Returns: 1 when the signature could be parsed, 0 otherwise.
+ *  Args: ctx:      a secp256k1 context object
+ *  Out:  sig:      a pointer to a signature object
+ *  In:   input:    a pointer to the signature to be parsed
+ *        inputlen: the length of the array pointed to be input
+ *
+ *  This function will accept any valid DER encoded signature, even if the
+ *  encoded numbers are out of range. In addition, it will accept signatures
+ *  which violate the DER spec in various ways. Its purpose is to allow
+ *  validation of the Bitcoin blockchain, which includes non-DER signatures
+ *  from before the network rules were updated to enforce DER. Note that
+ *  the set of supported violations is a strict subset of what OpenSSL will
+ *  accept.
+ *
+ *  After the call, sig will always be initialized. If parsing failed or the
+ *  encoded numbers are out of range, signature validation with it is
+ *  guaranteed to fail for every message and public key.
+ */
+int ecdsa_signature_parse_der_lax(
+    const secp256k1_context* ctx,
+    secp256k1_ecdsa_signature* sig,
+    const unsigned char *input,
+    size_t inputlen
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
+
+#ifdef __cplusplus
 }
-
 #endif
+
+#endif /* SECP256K1_CONTRIB_LAX_DER_PARSING_H */
This page took 0.027224 seconds and 4 git commands to generate.